打造一个生命周期感知的MVP架构

很久没写Blog了,这两年也积累了比较多的知识和总结。也实现了不少的业务,以及针对部分业务的优化,发现呢有些知识还是可以分享出去的,只是之前一直在纠结会不会被人看不起什么的,之后才发现多虑了。毕竟放出去之后,不同程序员的思维集合起来,也许这个框架还能发展得更加快速、稳定。

可能之后都会两天一更,或者一星期两篇文章这样的速度更新下下。

感慨不多说了,首先放出自己写的一个生命周期感知的MVP架构

(PS:当前的架构是直接运用到一个线上项目了,成果也颇丰,结合自己封装的BaseMVPActivity,BaseMVPFragment一套组件使用,也是美滋滋的。)


生命周期感知的MVP?幌子?还是单纯的MVP?

什么是MVP?能点进来的小伙伴我都相信你都用过MVP了。

至于什么是生命周期感知?先看看这样一个场景:

    在Presenter层处理业务逻辑,多多少少会涉及到网络请求,假若你用的是OkHttp、抑或是Retrofit+RxJava作为网络请求,那么就会存在异步请求回调UI的情况,但是我们知道OkHttp他不是和Context生命周期绑定的(阅读源码),Retrofit+RxJava也是的,除非你自己加上了RxLifeCycle的组件支持,但是RxLifeCycle有个问题,我需要bindActivity,那么这个Activity怎么传递进去呢?

原本MVP的设计模式,就是让Presenter层是无法感知View层的Context存在的,假若打通了这个流程,无异于增加了MVP的复杂度。

以下是RxLifeCycle使用(这个bindActivity的对象需要怎么传递呢?)

myObservable
    .compose(RxLifecycleAndroid.bindActivity(lifecycle))
    .subscribe();

    那么问题就来了,因为我Presenter层是不知道Activity或者Fragment的生命周期的,假若在请求回调的期间,我的Activity或者Fragment需要销毁了,但是由于请求回调占用着View层,那么我们的Activity和Fragment就出现了内存泄漏,内存多处泄漏的情况下,还可能直接出现空指针异常(因为泄漏的Activity部分的控件可能已经被回收了,但是继续调用View层控件。)那么App就直接crash掉了。

   我们都知道OkHttp里面的请求是可以通过

OkHttpClient.dispatcher().cancelAll()

去取消请求,而Retrofit+Rxjava 就可以通过Observer中的onSubscribe函数,通过一个Disposable列表记录请求,然后在合适的时机去遍历取消就Ok了。

 

合适的时机?合适的时机在哪里了?

用脚趾头扣动了脑袋瓜想想,也就只有在Activity或者Fragment的onDestory回调的时候了。

时机找到了,生命周期怎么才能从View层传递到Presenter层呢?恰逢AndroidJetPack(后面迭代后改成AndroidX了)的诞生,使我有这个想法封装了一个LifeCycleMVP的框架。

Google地址:https://developer.android.com/jetpack/

因为公司可以翻墙,所以看的都是英文文档。关于JetPack的组件,我会另外开一个篇章去写。

LifeCycle作为Google JetPack 框架下的一个构建工具,Google也是心疼Android开发者,深知Android开发中Activity和Fragment生命管理的问题。特意除了一套LifeCycle供我们使用。

这上面的意思大概就是:LifeCycle是一个轻量的生命周期管理组件,通过监听回调的方式,实现生命周期的监听与回调。例如管理Activity和Fragment的生命回调。

实际上用着也很好用,很简单。因为在AppCompatActivity里面就支持了LifeCycle组件了。所以两三句代码就搞掂了生命周期的响应了

暂时先说下LifeCycle组件的三个类:

LifeCycleOwner:生命周期持有者,一个接口。用于提供生命周期相关回调(Activity的提供实现最后在一个叫SupportActivity,里面就实现了当前接口,用于提供当前LifeCycleOwner对象)

LifeCycleObserver:生命周期观察者,一个接口,用于实现并监听生命周期回调

LifeCycleRegistery:生命周期注册表,主要是关联生命持有者和观察者、控制事件回调给哪个观察者、生命周期绑定处理等。

详细的实现可以自己看看源码(不会很复杂),也可以跳转到这里:待补充

gradle引用:compile "android.arch.lifecycle:extensions:1.1.1"

 

前戏做足,现在就是撸代码的时刻了。

首先MVP开发模式中,我们先定义一套MVP层的协议,IBaseView,IBasePresenter。

定义一个IBaseView的接口先,可以用于统一管理View层对象。

实现什么函数无伤大雅,可以根据自己业务需求实现。

IBaseView.java

/**
 * @Author:Rayman
 * @Date:2018/10/17
 * @Description: View实现的接口
 */
public interface IBaseView {

    /**
     * 显示错误,比如无数据、网络错误等等。
     *
     * @param msg 错误文案提示
     */
    void showErrorMsg(String msg);

}

View层回调自己弄,Presenter层回调才是关键。Presenter层我定义的函数有四个:

绑定View、View层onCreate回调(考虑到有的P层需要用到该生命周期回调)、View层onDestroy回调、其他生命周期回调

IBasePresenter.java

/**
 * @Author:Rayman
 * @Date:2018/10/17
 * @Description:Presenter的接口 .
 * 默认实现AndroidX LifeCycle组件
 **/
public interface IBasePresenter<T> extends LifecycleObserver {

    /**
     * 绑定View
     *
     * @param view
     */
    void setView(@NonNull T view);

    /**
     * View层OnCreate事件回调
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onViewCreate();

    /**
     * View层onDestroy事件回调
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onViewDestroy();

    /**
     * 生命周期切换时候回调
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifeCycleChange(@NonNull LifecycleOwner owner,
                           @NonNull Lifecycle.Event event);

}

 

按照上面定义完成之后,初步的LifeCycleMvp框架是出来了,剩下的就是怎么走一个MVP的流程和怎么实现生命周期的绑定。

 

绑定生命周期

绑定生命周期这个呢~需要配合BaseActivity或者BaseFragment使用。

我这里就放出一个BaseMVPActivity,其他情况的使用也是如此。

主要是继承了BaseActivity,然后实现了IBaseView接口,内部还创建了一个IBasePresenter的成员变量。

然后在onCreate生命周期回调的时候,进行View层和Presenter的绑定,同时也绑定生命周期

/**
 * @Author:Rayman
 * @Date:2018/10/17
 * @Description:继承BaseActivity,整合MVP架构
 */

public abstract class BaseMvpActivity<D> extends BaseActivity implements IBaseView<D> {

    /**
     * description:MVP层关联
     **/
    private IBasePresenter mPresenter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        initMvp();
        super.onCreate(savedInstanceState);
    }

    /**
     * 初始化MVP架构
     */
    private void initMvp() {
        mPresenter = createPresenter();
        if (mPresenter != null) {
            mPresenter.setView(this);

            // 初始化MVP的时候,添加生命周期监听
            getLifecycle().addObserver(mPresenter);
        }
    }

    /**
     * 设置当前模块的P层,需要在initView之前调用
     *
     * @return
     */
    protected abstract IBasePresenter createPresenter();

}

生命周期绑定之后,就剩下使用了。

 

如何使用?

首先实现一个业务逻辑的Presenter层,然后继承IBasePresenter。

为了方便演示,我随便拿了项目的一个Contract类

IUserChangeAccountContract.java

/**
 * @Author:Rayman
 * @Date:2018/10/21
 * @Description:用户模块---更换账号
 */
public interface IUserChangeAccountContract {

    interface IUserChangeAccountModel {

        /**
         * description:更换账号
         **/
        Observable<CommonData> changeAccount(String realName , String account);
    }

    interface IUserChangeAccountPresenter extends IBasePresenter<IUserBindAliAccountView> {

        void changeAccount(String realName , String account);
    }

    // 当前这个IBaseLoadingView也是继承IBaseView的。
    interface IUserChangeAccountView extends IBaseLoadingView<CommonData> {

        void changeAccountSuccess(String msg);
    }

}

然后再看看IUserChangeAccountPresenter的实现

UserChangeAccountPresenter.java

/**
 * @Author:Rayman
 * @Date:2018/10/21
 * @Description:用户模块---P层---更换账号
 */
public class UserBindAliAccountPresenter implements IUserBindAliAccountContract.IUserBindAliAccountPresenter {

    private IUserBindAliAccountContract.IUserBindAliAccountView mView;
    private IUserBindAliAccountContract.IUserBindAliAccountModel mModel = new UserBindAliAccountModel();
    private ArrayList<Disposable> mDisposableList = new ArrayList();
    private int requestCount = 0;

    @Override
    public void setView(IUserBindAliAccountContract.IUserBindAliAccountView view) {
        mView = view;
    }

    @Override
    public void onViewCreate() {
        LogUtils.error("View创建");
    }

    @Override
    public void onViewDestroy() {
        for(int i = 0,size = mDisposableList.size();i < size; i++){
            Disposable disposed = mDisposableList.get(i);
            disposed.dispose();
        }
        LogUtils.error("View销毁请求:" + requestCount);
    }

    @Override
    public void onLifeCycleChange(LifecycleOwner owner, Lifecycle.Event event) {
        LogUtils.error("View生命周期变换:" + event.name());
    }

    @Override
    public void changeAccount(String realName,String account) {
        mView.showLoading();
        requestCount++;
        mModel.changeAccount(realName, account)
                .subscribe(new RxSubscriber<CommonData, IUserBindAliAccountContract.IUserBindAliAccountView>(mView) {
                    @Override
                    public void onSubscribe(Disposable d) {
                        super.onSubscribe(d);
                        mDisposableList.add(d);
                    }

                    @Override
                    public void onNext(CommonData t) {
                        super.onNext(t);
                        mView.bindAliAccountSuccess("绑定成功");
                        UserUtils.updateBindAccount(account, realName);
                    }
                });
    }
}

 

整个流程就是这样了,上面的例子我就是用Retrofit+RxJava的方式请求的。然后在onSubscribe中将RxJava的事件处理添加到一个列表,然后在ViewDestroy的时候遍历销毁。

 

最后我们来看下Log的输出还有通过AndroidProfiler查看下,多个请求是否会引起Activity内存泄漏。

待补充----

 

好了~代码就上面所述的,联动下一篇---基于LifeCycleMvp再扩展,然后发布一个GitHub的开源库。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值