最近逛各大论坛时经常听到大家提及MVP(Model-View-Presenter)
模式在Android开发中的优势,比如:易于维护
,易于测试
,松耦合
,复用性高
等优点。于是自己就百度,Google一番,看了一些别人对MVP的讲解和使用示例,感觉真心不错,好用,不足的是在网上搜索到的关于MVP的大多都是讲理论,稍微好点的会附带一个简单的demo,并没有讲MVP在Android开发项目时如何较好的设计和需要注意的一些东西,这就导致我们这些不熟悉MVP的小白,了解了MVP的皮毛,但不敢用于实际项目中。经过最近一段时间对MVP的了解和学习,我自己慢慢总结出了一个MVP简易的开发模版,在这分享出来,供大家参考,不足之处请多多指教。……_
不了解MVP的可以参考一下文章,写的不错的
MVP模式简介
- 从图中可知View不直接与Model交互,而是通过与Presenter来与Model间接交互。
- Presenter与View的交互是通过接口来进行的。
- Presenter与Model的交互也是通过接口来进行的。
- 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。
- Presenter拥有View和Model的实例。
MVP在Android开发中内存溢出问题
(参考Android源码设计模式解析与实战)
-
Android开发中我们必须要跟Activity打交道,跟Activity打交道时,我们自然而然要考虑到生命周期的问题。在MVP模式中Activity作为View层,它是被Presenter持有强引用的,如果我们在Presenter中做一些耗时的处理
网络请求等
,并且Activity在耗时操作完成之前销毁,这样就导致Presenter一直持有Activity的引用,Activity无法被回收,此时就会发生内存泄漏。解决办法就是让Presenter 持有Activity的弱引用。
1创建一个Presenter抽象命名为BasePresenter,它是一个泛型类,泛型类型为View角色要实现的接口类型。代码如下:
/** *
* @param <V>代表view接口
*备注:ImvpBaseView 为一个空接口,
明确泛型 V 是一个View角色要实现的接口类型
(所有的View接口都要继承ImvpBaseView接口可以把所有接口都要拥有的方法放到ImvpBaseView)
*/
public abstract class BasePresenter <V extends ImvpBaseView> {
protected Reference<V>mViewRef;
//建立关联
public void attachView(V view){
mViewRef=new WeakReference<V>(view);
}
//获取view
protected V getView(){
return mViewRef.get();
}
//判断是否与View建立了关联
public boolean isViewAttached(){
return mViewRef!=null && mViewRef.get()!=null;
}
//该方法在activity或者Fragment的onDestory中调用
public void detachView(){
if(mViewRef!=null){
mViewRef.clear();
mViewRef=null;
}
}}
2.创建MVPBaseActivity基类,通过这个基类的声明周期函数来控制它与Presenter的关系,代码如下:Fragment的基类创建类似
/** *
* @param <V> 代表View接口
* @param <P> 代表代理presenter
*/
public abstract class MVPBaseActivity<V extends ImvpBaseView,
P extends BasePresenter<V>> extends Activity {
protected P mPresenter;
@SuppressWarnings("unchecked")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();
mPresenter.attachView((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mPresenter != null)
mPresenter.detachView();
}
protected abstract P createPresenter();
}
经过1,2步的处理我们就可以避免使用MVP时造成内存泄漏的问题了。
读到这里,有些读者可能抱怨说, 博客标题叫android中使用MVP开发简单模版
,但是以上都是MVP模式的简介和android中使用时注意的问题,并没有涉及到模版,这不是坑人吗?人与人之间的信任呢?诚实守信是我们中华的美德,作为天朝的开发者,怎能不弘扬呢?
hah客官莫急,下面就是我们的菜啦
作为开发者我们肯定有自己的开发基本库,用于收藏一些公共开发使用的工具和功能。上面的MVP的抽象的泛型的解决办法一看就是通用的,肯定要收藏到我们的基本开发库中,方便以后我们开发使用。就拿我个人而言,开发项目时我所有的Activity继承于BaseActivity(在实际项目)
,BaseActivity继承于AndBaseActivity(基础开发库中)
,AndBaseActivity继承于AppCompatActivity(当然你可以使用Activity)
如下图:
如果我将MVPBaseActivity收入到我的基本库中时,继承结构如下图:
备注:Fragment的结构设计类似,这里就不给出了。
完整的MVP的简单模版的简易UML图如下:
第一层是在基本类库中解决通用的功能比如:上文讲到的MVP 造成的内存泄漏。
第二层是在我们实际项目中的,目的是放项目中一些共用的方法和属性。
第三层就是我们具体的Model-View-Presenter,处理具体的业务逻辑和展示具体的view。
MVP模式中,Presenter拥有的Model和View都是接口实例,这就是说我们在做一个功能是就要创建一套Model-View-Presenter。
这里拿获取天气信息使用MVP模式为例,我们就需要创建WeatherPresenter,IWeatherModel接口
,IWeatherView接口
,
IWeatherModel的实现类WeatherModelImpl, IWeahterView的实现类WeatherShowActivity。从这可以看出如果我们一个项目做完,会创建很多的接口和实现类,接口爆炸的赶脚,我们可以简化Model的设计,来减少接口。
Model层主要用于本地数据的增删改查个人观点
,功能比较明确,所以可以用一个接口IBaseMode<T>把所有的方法定义好,并通过SampleModelAdapter<T>实现该接口的所有方法空实现
,然后我们具体的model继承SampleModelAdapter<T>去重写自己业务具体要做的数据保存方法,比如有些数据只需要缓存,就不用重写数据库的方法,而有些数据要保存在本地数据库中,也就不用重写缓存方法。
以上只是个人在学习MVP模式开发中,总结的简单模版设计,不足之处,请留言,本人会尽快修正!Thanks…………Y(_)Y