Android MVC架构和MVP架构以及区别
一、MVC架构:
MVC就是Model-View-Controller:
(数据模型)Model:数据的封装和保存,业务逻辑和实体模型
(视图)View:视图界面,对应于布局文件
(控制器)Controller:业务逻辑,对应于Activity、Fragment等
它们之间的关系如下图所示:
View传送指令到Controller,Controller完成业务逻辑后,改变Model的状态,Model将新的数据发送到View,这就是MVC模式的处理逻辑。
实例【以Retrofit联网为例】
先看主页布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btnMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="click here to connect by retrofit"
android:textAllCaps="false" />
<TextView
android:id="@+id/tvMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp" />
</LinearLayout>
作者:HELLO丶GUY
链接:http://www.jianshu.com/p/894420ac8fdc
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
点击按钮进行联网并且把联网获取到的数据显示在textview中,如果失败则显示联网数据获取失败。
这里主要贴出model与controller包下的代码。
model-KpiInfoModel.java
public interface KpiInfoModel {
void getKpiInfo(Map<String, String> params, OnKpiInfoListener listener);
}
model-OnKpiInfoListener.java
public interface OnKpiInfoListener {
void onSuccess(ResultBean<KpiInfoPo> resultBean);
void onFailed();
}
以上KpiInfoModel 主要是用于提供进行联网动作的入口方法,这里看起来会有一点吃力。同样的,OnKpiInfoListener 提供了联网以后的操作方法。然后我们需要去实现这两个接口,并且重写里面的方法。
model-KpiInfoModelImp.java
public class KpiInfoModelImp implements KpiInfoModel {
@Override
public void getKpiInfo(Map<String, String> params, final OnKpiInfoListener listener) {
Call<ResultBean<KpiInfoPo>> call = MainApplication.factory.getKpiInfo(params);
call.enqueue(new Callback<ResultBean<KpiInfoPo>>() {
@Override
public void onResponse(Call<ResultBean<KpiInfoPo>> call, Response<ResultBean<KpiInfoPo>> response) {
if (response.isSuccessful() && response.body() != null) {
listener.onSuccess(response.body());
} else {
onFailure(call, null);
}
}
@Override
public void onFailure(Call<ResultBean<KpiInfoPo>> call, Throwable t) {
listener.onFailed();
}
});
}
}
作者:HELLO丶GUY
链接:http://www.jianshu.com/p/894420ac8fdc
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上就是联网的model,并且以及写好了实现类,用于在controller中使用。
controller-MainActivity.java
public class MainActivity extends AppCompatActivity implements OnKpiInfoListener {
private Button btnMain;
private TextView tvMain;
private KpiInfoModelImp kpiInfoModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.acticity_home);
initView();
kpiInfoModel = new KpiInfoModelImp();
btnMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> params = new HashMap<>();
params.put("user_id", "198");
kpiInfoModel.getKpiInfo(params, MainActivity.this);
}
});
}
private void initView() {
btnMain = (Button) findViewById(R.id.btnMain);
tvMain = (TextView) findViewById(R.id.tvMain);
}
@Override
public void onSuccess(ResultBean<KpiInfoPo> resultBean) {
tvMain.setText(resultBean.getResult_data().toString());
}
@Override
public void onFailed() {
tvMain.setText("数据获取失败");
}
}
作者:HELLO丶GUY
链接:http://www.jianshu.com/p/894420ac8fdc
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
通过以上实例代码可以看出,activity只起到了和view互动的作用,只针对view进行操作,而联网部分则全部是在model里,这样对与业务的分离具有好处。但也具有一定的劣势,可以看出model的这块代码较为琐碎。
二、MVP架构:
MVP是Model-View-Presenter,它们的作用如下:
Model:业务逻辑和实体模型,用来操作实际的数据,包含Bean和Model的抽象接口来降低耦合。
View:就是Android中的视图,需要建立一个View的抽象接口View Interface。通过实现View的接口来实现View与Presenter的交互,从而降低耦合。对应于Activity,负责View的绘制与用户交互;
Presenter:View和Model的中间枢纽,处理和用户交互的逻辑。
作者:ibinbin
链接:http://www.jianshu.com/p/bd99bda72912
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
通过一个物联网的例子来理解MVP模式:
View层:
/**
* ViewInterface
* 定义一些通用的view接口
*/
public interface LoadDataView {
/***
* 耗时操作,加载数据,显示Progress
*/
void showLoading();
/***
* 隐藏Progress
*/
void hideLoading();
}
/**
* 更细小的,用来显示图书细节的View接口
*/
public interface LoadBookView extends LoadDataView {
void showDetailsView(BookEntity entity);
}
/***
* Fragment,属于View层,实现了ViewInterface(LoadBookView)
*/
public class BookDetailFragment extends Fragment implements LoadBookView{
/**图书条形码ISBN号*/
public static final String ISBN = "9787121060748";
/**持Presenter对象*/
private BookDetailsPresenter presenter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initWidget();
presenter = new BookDetailsPresenter(getActivity(), ISBN); // 实例化一个presenter对象
presenter.setView(this); //让Presenter持一个ViewInterface实例(LoadBookView)
presenter.loadData(); //告诉Presenter快给我加载Data
}
@Override
public void showDetailsView(BookEntity entity) {
//更新UI等操作
}
@Override
public void showLoading() {
rlProgress.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
rlProgress.setVisibility(View.GONE);
}
}
作者:ibinbin
链接:http://www.jianshu.com/p/bd99bda72912
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2、Presenter层:
public class BookDetailsPresenter {
/**持一个Model层的对象,用来从网页接口Rest Api中提取数据*/
private RestApi restApi = null;
/**一个ViewInterface对象,用来回调Data给View*/
private LoadBookView loadBookView;
private String isbn;
public BookDetailsPresenter(Context context, String isbn) {
restApi = new RestApiImpl(context);
this.isbn =isbn;
}
public void setView(LoadBookView loadBookView) {
this.loadBookView = loadBookView;
}
public void loadData() {
loadBookView.showLoading();
//耗时操作,开个线程异步的加载数据
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
restApi.getBookDetailByIsbn(isbn, bookDetailsCallback);
}
});
thread.start();
}
//匿名内部类,接收bookDetailCallback的回调数据
private RestApi.BookDetailsCallback bookDetailsCallback = new RestApi.BookDetailsCallback() {
@Override
public void onBookEntityLoaded(BookEntity bookEntity) {
notifyDataLoadedSuccessful(bookEntity);
BookDetailsPresenter.this.loadBookView.hideLoading();
}
@Override
public void onError(Exception e) {
//异常后的相关处理
}
};
/***
* 通知获取数据成功了,赶快通知UI更新吧
*/
private void notifyDataLoadedSuccessful(final BookEntity bookEntity) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
BookDetailsPresenter.this.loadBookView.showDetailsView(bookEntity);
}
});
}
}
作者:ibinbin
链接:http://www.jianshu.com/p/bd99bda72912
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3、Model层:
/***
* 整个应用程序需要的数据实体类
*/
public class BookEntity {
//一些set,get方法
}
/**
* 一个接口,用来从rest api api获得数据,它的实现在RestApiImpl中
*/
public interface RestApi {
String API_ISBN_BASE_URL = "https://api.douban.com/v2/book/isbn/";
/***
* 更细小的接口,用来将获取到的数据,回调给它的调用者
*/
interface BookDetailsCallback {
void onBookEntityLoaded(BookEntity bookEntity);
void onError(Exception e);
}
/**
* 从网络获取数据,然后通过bookDetailCallback回调给Presenter
* @param isbn
* @param bookDetailsCallback
*/
void getBookDetailByIsbn(final String isbn, final BookDetailsCallback bookDetailsCallback);
}
作者:ibinbin
链接:http://www.jianshu.com/p/bd99bda72912
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、MVP和MVC的区别
MVP架构:
View不直接与Model交互,而是通过与Presenter交互来与Model间接交互。
Presenter与View的交互是通过接口来进行的。
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。
MVC架构:
View可以与Model直接交互。
Controller是基于行为的,并且可以被多个View共享。
可以负责决定显示哪个View。
MVC跟的MVP进行对比,就是省去mvp中的presenter,mvp中把mainactivity的接口实现类传入到presenter中,来拿到数据去进行model中的业务逻辑,model中再回调mainactivity的那个接口实现来进行视图更新,而mvc则是直接用mainactivity来与model打交道。