Android mvp模式已经出来了很长一段时间了,先来看一下mvc和mvp的对比。
(
demo地址: https://github.com/zhangzeyan/simple_mvp)
MVC架构
- M : 业务层和模型层,相当与javabean和我们的业务请求代码
- V : 视图层,对应Android的layout.xml布局文件
- C : 控制层,对应于Activity中对于UI 的各种操作
MVP架构
- M : 还是业务层和模型层
- V : 视图层的责任由Activity来担当
- P : 新成员Prensenter 用来代理 C(control) 控制层
mvc和mvp交互方式区别示意图:
直接看概念,可能比较朦逼。下面,我们通过一个demo来看一下mvp到底要怎么写。
1.先看Activity主要需要承担的任务:
我们新建一个MVPActivity继承activity,也就是相当于view层。在onCreate里面,有如下代码片段。(具体代码请看demo,这里只提供片段代码做分析)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp)
//初始化控件
mvpListView = (ListView)findViewById(R.id.mListView);
mvpListView.setOnItemClickListener(this);
pb = (ProgressBar) findViewById(R.id.mLoading);
userBeanList = new ArrayList<>();
adapter = new UserDataAdapter(this, userBeanList);
mvpListView.setAdapter(adapter);
//实例化Presenter
mvpPresenter = new MVPPresenter(this);
//调用Presenter层请求数据
mvpPresenter.requestForData();
}
在activity里,承担的主要工作是对控件进行初始化,并实例化presenter层,但并不请求数据。请求数据交给了presenter层, activity只是调起presenter的请求数据方法(具体presenter里面是如何实现请求数据,跟activtiy无关,activity也无需关心)。对比一下,在mvc模式中,通常,我们直接将请求数据的操作放到activity代码里,这样当项目越来越庞大时候,代码就显得很臃肿,activity既充当控件的处理,又充当数据的请求,这会导致后期项目很难维护。
2.接下来,我们看一下present层:
public class MVPPresenter {
private MVPViewInter mvpView;
private RequestData requestData;
private Handler mHandler;
public MVPPresenter(MVPViewInter mvpView) {
this.mvpView = mvpView;
requestData = new RequestDataImp();
mHandler = new Handler(Looper.getMainLooper());
}
public void requestForData(){
mvpView.showLoading();
requestData.requestForData(new RequestData.OnRequestListener() {
@Override
public void onSuccess(final List<UserBean> data) {
mHandler.post(new Runnable() { //需要使用handler去更新界面
@Override
public void run() {
mvpView.hideLoading();
mvpView.setListItem(data);
}
});
}
@Override
public void onFailed() {
mvpView.showMessage("请求失败");
}
});
}
public void onItemClick(int position){
mvpView.showMessage("点击了item"+position);
}
public void onDestroy(){
mvpView = null;
}
}
首先,RequestData和RequestDataImp是什么鬼,其实这两个是只是模拟网络请求,得到数据而已,你可以换成自己系统请求网络的代码,而UserBean明显就是model层。
其次,我们看到presenter的构造方法里面,需要传一个MVPViewInter对象,这个又是什么鬼?其实,这个是View层抽取出来需要时实现的接口。也就是View层需要做的一些具体操作,这里,我们通过接口编程来实现。
public interface MVPViewInter { /** * 显示loading progress */ void showLoading(); /** * 隐藏loading progress */ void hideLoading(); /** * ListView的初始化 * @param data */ void setListItem(List<UserBean> data); /** * Toast 消息 * @param message */ void showMessage(String message); }
当通过网络请求得到数据成功后,执行了下面代码:
mvpView.hideLoading();
mvpView.setListItem(data);
说明,view得到的数据,是通过presenter层传过来的,而不是直接在view获取的。这就很好的降低了藕合度。
那么,刚才所创建的View层接口MVPViewInter到底由谁来继承呢?很明显,当然是View层,也就是activity这个类:
public class MVPActivity extends Activity implements MVPViewInter {...}
我们看到MVPActivity实现了MVPViewInter接口,在重写的方法里,代码都是只负责一些关于控件上的操作,而跟请求数据,处理数据,完全没关系。
@Override
public void showLoading() {
pb.setVisibility(View.VISIBLE); //进度条显示
}
@Override
public void hideLoading() {
pb.setVisibility(View.GONE); //进度条隐藏
}
@Override
public void setListItem(List<UserBean> data) {
userBeanList.clear();
userBeanList.addAll(data);
adapter.notifyDataSetChanged(); //适配器更新
}
@Override
public void showMessage(String message) {
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
到此,我们可以看到mvp模式的确降低了藕合度,使activity不再做过多的业务处理,交给了prensenter层,当然,这只是mvp最简单的用法,后面,我们会学习mvp的深入用法。
最后,附上这个demo的下载地址(包含了mvc和mvp两种模式的对比):
https://github.com/zhangzeyan/simple_mvp