编辑于2017年3月24日
参考:《Android源码设计模式 解析与实战》一书
大致分包如下图
M:负责获取,存储,检索等操作数据,持有数据对象并直接对其进行操作。
V: View Interface:抽取UI及数据展示隐藏等相关操作的方法(可能多个view用到这些方法)。
View:负责绘制、初始化UI;持有Presenter对象,view把与数据相关的业务逻辑都交给Presenter;持有没有数据的数据对象,数据需要presenter传递过来;一些点击后跳转一类的操作仍由其负责。
P:同时持有View和Model的引用;因为view需要把与数据相关的业务逻辑都交给Presenter,需要调用presenter,所以view是传参(即构造方法的形参传过来的);model没有办法主动从Presenter那拿回数据继续处理,也就是model没办法调用Presenter,所以model是实参。Presenter通知Model处理好数据并返回,调用了model的方法;Presenter拿到数据交给view展示,调用了view的方法(即view interface的方法);Presenter把数据交给model继续或者再次处理,调用了model的方法;上述三件事先后顺序根据具体情况决定,比如先获取数据调用model,再展示在UI上调用view,最后再存储数据调用model。
个人观点:MVP是View需要数据进行展示等相关操作(接口中的方法),于是便通知了presenter让其准备好数据;presenter本身并不持有数据,于是便让model获取数据并传给他,拿到数据后presenter自己并没有使用数据(不是全局变量);他把数据直接给了view让其去使用(是全局变量),同时把数据给了model让其继续处理;当view需要同样数据时可以自身获取,当view需要经过另外一种处理方式后的数据时便再次通知presenter。
MVP有很多优点,易于维护、易于测试、松耦合、复用性高、健壮稳定、易于拓展等。但是,由于Presenter经常性地需要执行一些耗时操作(等待Model执行完耗时操作),而Presenter持有了activity的强引用,如果在耗时操作结束前activity就被销毁了,就会导致Presenter一直持有activity对象,使得activity对象无法被回收,此时就发生了内存泄漏。
我们可以通过弱引用和activity、fragment的生命周期来解决这个问题。首先建立一个Presenter抽象,我们命名为BasePresenter,他是一个泛型类,泛型类型为view角色要实现的接口类型。具体代码如下:
public abstract class BasePresenter<V> {
/**@Field: (View接口类型的弱引用) */
protected Reference<V> mViewRef;
/**
* 建立关联
* @param view
*/
public void attachView(V view){
mViewRef=new WeakReference<V>(view);
}
/**
* 解除关联
*/
public void detachView(){
if (mViewRef!=null){
mViewRef.clear();
mViewRef=null;
}
}
/**
* 判断是否与View建立了关联
* @return
*/
public boolean isViewAttached(){
return mViewRef!=null&&mViewRef.get()!=null;
}
/**
* 获取View
* @return
*/
protected V getView(){
return mViewRef.get();
}
}
view类型通过BasePresenter的泛型类型传递进去,Presenter对这个view持有弱引用。通常情况下这个view类型应该是实现了某个特定接口的activity或者fragment等类型。
创建一个BaseActivity基类,通过这个基类的生命周期函数来控制它与Presenter的关系,相关代码如下:
public abstract class BaseActivity<V,P extends BasePresenter<V>> extends Activity{
/**@Field: (与Presenter建立关系) */
protected P mPresenter;
/**
* 创建Presenter
* @return
*/
protected abstract P createPresenter();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter=createPresenter();
mPresenter.attachView((V)this);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView();
}
}
同理,BaseFragment相关代码如下:
public abstract class BaseFragment<V,P extends BasePresenter<V>> extends Fragment {
/**@Field: (与Presenter建立关系) */
protected P mPresenter;
/**
* 创建Presenter
* @return
*/
protected abstract P createPresenter();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter=createPresenter();
mPresenter.attachView((V)this);
}
@Override
public void onDestroy() {
super.onDestroy();
mPresenter.detachView();
}
}