Android的MVP模式开发这篇博客中,已经初步讲解了如何使用和设计MVP模式,但是这个博客最后末尾还留下了个一个问题就是:虽然对各个模块进行解耦了,能够对View中的代码进行减负,但是也正是如此,才会对对没用的View进行引用,虚拟机根本无法回收,最后导致内存泄露。

下面来讲下如何去创建基类,来优化一下MVP模式。

1. 创建M/V/P的基类接口

1.1. 创建View的基类接口

public interface IBaseView {

    /**
     * 显示加载
     */
    void showLoadingView();

    /**
     * 隐藏加载框
     */
    void hideLoadingView();


    /**
     * 获取上下文
     *
     * @return Context
     */
    Context getContext();
}

1.2. 创建Model的基类接口

public interface IBaseModel {
}

1.3. 创建Presenter的基类接口

public interface IBasePresenter<V extends IBaseView> {

    /**
     * 依附生命view
     *
     * @param view
     */
    void attachView(V view);

    /**
     * 分离View
     */
    void detachView();

    /**
     * 判断View是否已经销毁
     *
     * @return
     */
    boolean isViewAttached();
}

2. 实现Presenter基类

public abstract class BasePresenter<M extends IBaseModel, V extends IBaseView> implements IBasePresenter<V> {

    private V mView;
    private M module;
    private WeakReference<V> mWeakReference;

    /**
     * 绑定view
     *
     * @param view
     */
    @SuppressWarnings("unchecked")
    @Override
    public void attachView(V view){
        mWeakReference = new WeakReference<>(view);
        mView = (V)Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new MvpViewHandler(mWeakReference.get()));
        if (this.module == null){
            this.module = createModule();
        }
    }

    /**
     * 分离View
     */
    @Override
    public void detachView(){
        this.module = null;
        if (isViewAttached()){
            mWeakReference.clear();
            mWeakReference = null;
        }
    }

    /**
     * 判断view是否销毁
     *
     * @return
     */
    @Override
    public boolean isViewAttached(){
        return mWeakReference != null && mWeakReference.get() != null;
    }


    /**
     * 获取view
     *
     * @return view
     */
    protected V getView(){
        return mView;
    }

    /**
     * 获取module
     *
     * @return model
     */
    protected M getModule(){
        return module;
    }

    protected abstract M createModule();

    /**
     * View代理类:防止页面关闭了P层异步调用V方法,造成空指针异常
     */
    private class MvpViewHandler implements InvocationHandler {

        private IBaseView mvpView;

        public MvpViewHandler(IBaseView mvpView) {
            this.mvpView = mvpView;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 如果view层没有被销毁,那么就调用view层的方法
            if (isViewAttached()){
                return method.invoke(mvpView, args);
            }
            // P层不关心view层的返回值
            return null;
        }
    }
}

3. 创建Activity的基类

public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IBaseView{


    protected P presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(setLayoutResId());
        initView();
        // 创建Presenter
        presenter = createPresenter();
        if (presenter != null){
            presenter.attachView(this);
        }
        initEventAndData();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter != null){
            presenter.detachView();
            presenter = null;
        }
    }

    /**
     * 创建Presenter
     *
     * @return P Presenter对象
     */
    protected abstract P createPresenter();

    /**
     * 插入布局文件
     *
     * @return
     */
    protected abstract int setLayoutResId();

    /**
     * 初始化布局View
     */
    protected abstract void initView();

    /**
     * 初始哈化事件和数据
     */
    protected abstract void initEventAndData();
}

4. 在Activity中的使用

public class MainActivity extends BaseActivity<LogoutPresenter> implements ILoginOutView {
      @Override
    protected LogoutPresenter createPresenter() {
        mPresenter = new LogoutPresenter();
        return mPresenter;
    }

        @Override
    protected int setLayoutResId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initView() {
    }

     @Override
    protected void initEventAndData() {
    }

    @Override
    public Context getContext() {
        return this;
    }
    
   // ...等等View中的一些接口方法
}

让Activity去继承BaseActivity并实现View中的一些接口方法。