转:http://blog.csdn.net/qq_31852701/article/details/52946127java
首先MVP 是从经典的MVC架构演变而来,那咱们是否是要先说下何为MVC模式?面试
系统C/S(Client/Server)三层架构模型:正则表达式
1)视图层(View):通常采用XML文件对应用的界面进行描述,使用的时候能够直接引入,极为方便,能够的大大缩短开发时间,也可使用JavaScript+HTML等的方式做为View层,固然这里须要进行Java和JavaScript之间的通讯,幸运的是,Android提供了很是方便的通讯实现。业务逻辑层(BLL):它的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计,也便是说它是与系统所应对的领域(Domain)逻辑有关,不少时候,也将业务逻辑层称为领域层。数据库
2)控制层(Controller):Android的控制层的重任一般落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要经过Activity交割Model业务逻辑层处理。编程
3)模型层(Model):对数据库的操做、以及其余和数据有关的的操做都应该在Model里面处理,固然对业务计算等操做也是必须放在的该层的。就是应用程序中二进制的数据。设计模式
三层结构架构三层间的交互及做用以下图所示:缓存
传统的MVC模式是很不错,咱们也很熟悉,毕竟用了这么多年了。(忽然想到以前去一家公司面试他问个HelloWord的Android项目是否是MVC,我说不是,他说回答错误,阿西吧!)网络
在Android项目上你会发现Activity的责任过重,什么东西都要放在Activity中,最终致使了Activity太过臃肿。虽然能抽的都抽出来了,可是会发现代码仍是不少,试想下上千行代码尚未注释,能不晕?即便是本身写的,过些日子去看也有些晕晕的吧?架构
尤为代码敲完,一个月后需求又改了,从600、700行代码中找到要修改的地方也是要一点功夫的。框架
为了给Activity减轻压力,这时候MVP出现了!
MVP有什么好处,为何要用MVP呢?
网上搜下一大堆MVP的各类好处,宝宝总结下主要有如下几点:
下面开始贴代码讲解
先来说View IBuyBookView
这里主要是包含了Activity的一系列关于UI操做,而后用咱们的Activity是实现,这样Presenter就能够调用了。
public interface IBuyBookView { /** * 提示toast */ void showToast(String msg); /** * 刷新adapter */ void refreshAdapter(); void onEmpty(); }
接下来说Model IBuyBookModel BuyBookModel
主要是写了几个方法供BuyBookModel去实现
这里实现了IBuyBookModel,而后模拟了下网络请求,用随机来模拟请求成功与失败,因此若是有童鞋下载Demo发现进去怎么空白一片,那么请退出来多近几回,宝宝曾连续5次进去都是空白的,这运气也太背了吧。
这里贴上楼上那个回调接口,这里用了泛型,为何呢?为了多多复用。
public interface ValueCallBack<T> { void onSuccess(T t); void onFail(String code); }
接下来说Presenter BasePresenter IBuyBookPresenterBuyBookPresenter
这个是全部Presenter的基类,里面有个initData()方法,基本每一个Presenter都要处理网络请求吧,因此我就弄了这么一个基类,至于为何是抽象的而不是接口,这是由于抽象方便点吧,若是咱们往抽象类中添加新的方法(该方法不是抽象的),能够给他提供默认的实现,并且不要修改现有的代码,可是若是是接口的话,就要修改现有的代码了。指不定咱们之后要往这里加什么呢。
这里为何用了个泛型?为了让人一看这个Presenter就知道这对应着哪一个Activity,实际上这能够不加的,可是我以为加上去更好。便于后来人也便于本身之后再来修改这个类。
public abstract class BasePresenter<T extends BaseActivity> { abstract void initData(); }
这里主要写了个方法,以供BuyBookPresenter实现
public interface IBuyBookPresenter { List<BuyBookBean> getAdapterData(); }
这里首先实现现了IBuyBookPresenter继承了BasePresenter,而后重写一些方法。这里的构造方法是重点,在构造方法中,咱们须要传入一个IBookView,实际上咱们的Activity已经实现IBookView了,因此这里实际上传的是具体的Activity,也就是this就好了。而后model咱们能够直接new出来用,这里就new了。
在initData中咱们是进行了具体的网络请求,网络请求咱们是否是要弹一个Dialog出来,直接在这mView.loading();调用就好了。而后请求成功onSuccess()里面让Dialog消失,提醒适配器刷新。失败的话onFail()里面提示Dialog消失,而后ListView设置失败页面什么的。
public class BuyBookPresenter extends BasePresenter<BuyBookActivity> implements IBuyBookPresenter { private IBuyBookView mView; private IBuyBookModel mModel; public BuyBookPresenter(IBuyBookView iBuyBookView) { this.mView = iBuyBookView; this.mModel = new BuyBookModel(); } @Override public List<BuyBookBean> getAdapterData() { return mModel.getAdapterData(); } @Override public void initData() { //在这里弹出loading mModel.getTestData(new ValueCallBack<List<BuyBookBean>>() { @Override public void onSuccess(List<BuyBookBean> buyBookBeen) { //在这里取消loading //简单数据操做能够在presenter里完成 mModel.getAdapterData().addAll(buyBookBeen); mView.refreshAdapter(); } @Override public void onFail(String code) { //在这里取消loading mView.showToast(code); mView.onEmpty(); } }); } }
接下来说咱们的Activity BuyBookActivity BaseActivity
这是咱们Acticity的基类,能够看到这里有个泛型,注意了,前方高能。这个泛型还必须继承BasePresenter,这个首先为了让人一看到这个Activity就知道对应着那个Presenter;其次最重要的就是为了下面那个成员变量basepresenter,咱们写一个抽象的方法要求返回泛型T,而这个泛型T又继承了BasePresenter,那么咱们就获得了具体Presenter的成员变量,能够直接用这个成员变量来调用Presenter中的方法了。
这个就是最终具体的Activity了,能够看到这里都没什么逻辑,基本都是一些重写的方法。
public class BuyBookActivity extends BaseActivity<BuyBookPresenter> implements IBuyBookView { private ListView mListView; private BuyBookAdapter mAdapter; @Override BuyBookPresenter initPresent() { return new BuyBookPresenter(this); } @Override int getLayout() { return R.layout.activity_main; } @Override void initView() { mListView = (ListView) findViewById(R.id.listview); } @Override void onPrepare() { mAdapter = new BuyBookAdapter(this, basepresenter.getAdapterData()); mListView.setAdapter(mAdapter); basepresenter.initData(); } @Override public void showToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } @Override public void refreshAdapter() { mAdapter.notifyDataSetChanged(); } public void onEmpty() { mListView.setEmptyView(null); } }
最后虽然MVP模式有许多好处,可是有一个致命的缺点就是类太多,原本一个类最多变成了7个类,最少变成6个类(使用Contract协议类)。因此并非全部的页面都要用MVP模式的,很简单的页面就不必了,浪费时间是否是。
为何MVP模式利于单元测试?
Presenter将逻辑和UI分开了,里面没有Android代码,都是纯纯的java代码。咱们能够直接对Presenter写Junit测试