MVP介绍
MVP设计模式分成了View、Presenter、Model层,不同于原来的MVC,view中不在存放业务逻辑-只是展示页面,而由Presenter来统筹全局-处理逻辑
介绍几个官方MVP的写法
官方Demo
优秀实践
MVP与Lifecycle结合
MVP分析
官方MVP建议使用Activity里面创建Presenter,View使用Fragment,一图胜千言
实际中,我们的view可以是Activity或者Fragment,完全不需要一个Activity来嵌套一层view
####MVP模式封装
View
首先View接口,我们没有特定的方法需要实现,但是为了配合Presenter,我们的IView是个空接口。后面view只是简单的实现即可
1 2
| public interface IMvpView{ }
|
Presenter
Presenter中需要与View绑定,同时还需要知道view的生命周期-至少知道attach和detach
1 2 3 4 5 6 7 8 9 10 11 12
| public interface IMvpPresenter<V extends IMvpView> {
void onBind(V view);
void onViewAttach();
void onViewDetach();
}
|
Presenter的基类
Presenter中公共的,我们会做与view的绑定和解绑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public abstract class MvpPresenter<V extends IMvpView> implements IMvpPresenter<V> {
protected V mView;
protected Context mContext;
@Override public void onBind(V view) { mView = view; if (view instanceof Fragment) { mContext = ((Fragment) view).getContext(); } else if (view instanceof Activity) { mContext = (Activity) view; } else if (view instanceof View) { mContext = ((View) view).getContext(); } }
@Override public void onViewAttach() {
}
@Override public void onViewDetach() { mView = null; } }
|
- 在detach时吧mView置空,会导致调用mView出现空指针问题
这里我想过使用生成代码的方式判断mView的值,但是一直无法完美的实现。最后使用了空对象设计模式来实现
1 2 3 4 5 6 7 8 9 10
| private V mView;
protected V getView() { if (mView == null) { return createDummyView(); } return mView; }
protected abstract V createDummyView();
|
Helper类
View与Presenter的绑定,可以简单的在创建presenter的时候手动调用,如
1 2
| #View(Fragment|Activity) new XPresenter().onBind(this);
|
但是不乏我们忘记,所以可以写一个帮助类来完成
1 2 3 4 5 6 7 8 9 10
| public class MvpLifecycleHelper {
public static <V extends IMvpView, P extends IMvpPresenter<? super V>> P from(V view, P presenter) { presenter.onBind(view); return presenter; } }
|
这里写泛型的时候出现了一些小问题,可以查看另一篇博客
这样我们绑定的时候使用如下
1
| MvpLifecycleHelper.from(this,new LoginPresenter());
|
到此我们的MVP的简单封装已经完成。
但是现在presenter的周期还是需要view手动去调用的,这样还是很不友好
结合Lifecycle
其实我们要做的也很简单,只需要在onBind中添加presenter给lifecycle,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public abstract class PresenterLifecycle<V extends IMvpView> extends MvpPresenter<V> implements LifecycleObserver, IPresenterLifecycle<V> {
@Override public void onBind(V view) { super.onBind(view); if (view instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) view).getLifecycle(); lifecycle.addObserver(this); if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { this.onViewAttach(); } } }
@Override @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) public void onViewAttach() { mLifecycleSubject.onNext(Lifecycle.Event.ON_CREATE); }
@Override @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { mLifecycleSubject.onNext(Lifecycle.Event.ON_START); }
@Override @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onResume() { mLifecycleSubject.onNext(Lifecycle.Event.ON_RESUME); }
@Override @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { mLifecycleSubject.onNext(Lifecycle.Event.ON_STOP); }
@Override @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onViewDetach() { mLifecycleSubject.onNext(Lifecycle.Event.ON_DESTROY); super.onViewDetach(); } }
|
由于addObserver时,会调用一次对应的周期,所以我们可以完全不用手动调用onViewAttach()。
唯一存在的可能是我们在onResume才绑定presenter(这种可能很低),所以添加了一下周期判断
至此整个封装完成,源码已经同步到github,可下载使用