【Android】完善的mvp架构封装demo(可项目中使用)

相关知识和简版架构请参考:

【Android】mvp架构模式知识汇总 - 简书

demo地址

github

gitee

本文主要对mvp架构中的一些问题处理,从而完善封装。

1、关于内存泄漏;

说明: 内存泄漏主要原因是生命周期长的持有生命周期短的,导致持有的对象想要回收时无法回收。

场景:

其中mvp架构中,Presenter必须持有View;

Model一般会有异步请求,需要回调结果给Presenter(无论匿名内部类方式还是Presenter实现接口方式),那么Model则必定持有Presenter,同时可能需要使用到Context。

在Model中有耗时操作时就会导致此时Presenter和Context无法回收,而View和Context实际上就是Activity。

解决方法:

使用弱引用,封装在基类中,提供getisDestory方法。每次调用get前需要先判断下

示例:BasePresenter中

    /**
     * View是否有被回收
     *
     * @return
     */
    public boolean isViewDestory() {
        if (iViewWeakRef == null) {
            return true;
        }

        V view = iViewWeakRef.get();
        if (view == null) {
            return true;
        }
        if (view instanceof Activity) {
            Activity activity = (Activity) view;
            if (activity.isDestroyed() || activity.isFinishing()) {
                return true;
            }
        }

        return false;
    }
    /**
     * 与view解绑
     */
    public void detachView() {
        if (iViewWeakRef != null) {
            iViewWeakRef.clear();
        }
        iViewWeakRef = null;
        model.destory();
    }

BaseView中

    Context getContext();

BaseCallBack中

    Context getContext();

每次调用get时需要判断下

    /**
     * 请求数据入口
     * @param url
     */
    @Override
    public void requestData(String url) {
        if (isViewDestory()) {
            return;
        }

        getMvpView().showLoading();
        model.executeGetRequest(url);
    }

2、Context的获取方式;

使用接口获取,不要直接传入保存成成员变量,这样符合封闭原则,减少持有而需要防止内存泄漏的处理。

BaseView中

    Context getContext();

BaseCallBack中

    Context getContext();

如果使用传入的方式则是

    /**
     * 绑定mvp的View接口
     *
     * @param cxt
     * @param mvpView
     */
    public void attachView(Context cxt, V mvpView) {
        this.mContext = cxt;
        this.iView = mvpView;
    }

这样同时需要维护mContext、iView两个变量。

3、Presenter与Model交互方式;

Presenter以实现接口的方式传给Model,这样可以Presenter中代码更简洁,还可以让Model弱引用持有Presenter,并且通过接口方式获取Context,不用再次传入。

示例:

BaseModel中

public abstract class BaseModel<I extends BaseCallBack> {
    protected WeakReference<I> iCallBackWeakRef;

    public BaseModel(I iCallBack) {
        iCallBackWeakRef = new WeakReference<>(iCallBack);
    }

Presenter中

    @Override
    protected StudentModel createModel(BasePresenter presenter) {
        return new StudentModel(this);
    }
    /**
     * 请求数据入口
     * @param url
     */
    @Override
    public void requestData(String url) {
        if (isViewDestory()) {
            return;
        }

        getMvpView().showLoading();
        model.executeGetRequest(url);
    }

如果以匿名内部类的方式实现会直接导致内存泄漏,同时Presenter中代码没那么简洁。

示例:

Presenter中,此时,Model已经隐性强引用了Presenter。

 model.loadData(courseId, new HttpResponse<String>(String.class) {
            @Override
            public void onSuccess(String str) {

            }

            @Override
            public void onError(final String msg) {
               
            }
        });
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容