使用泛型,动态代理优化 mvp

解决问题

  1. Model 获取到数据之前,退出了 Activity,此时由于 Activity 被 Presenter 引用,而 Presenter 正在进行耗时操作,会导致 Activity 的对象无法被回收,造成了内存泄漏

通过在 BaseActivity 中重写onDestroy 来解绑presenter

  @Override
    protected void onDestroy() {
        super.onDestroy();
        //解绑Presenter
        presenter.detach();
    }
presenter
  /**
     * 解绑View
     */
    public void detach() {
        mView = null;
        mModel = null;
    }

这个时候带来的问题就是 Model 获取到数据之后调用 mView接口方法会空指针,所以做出优化

可以通过判断 mview 是否为空来解决,通过学习 retrofit的源码之后发现可以类似 ServiceMethod的创建使用动态代理来优化

public class BasePresenter<V extends BaseView, M extends BaseModel> {
    private V mView;
    private M mModel;

    /**
     * 绑定View
     *
     * @param view
     */
    public void attach(final V view) {
        //动态代理
        mView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //在View层显示数据之前用户可能退出了View层的页面,会在Activity的onDestroy()方法中会把mView置为null
                //由于View层都是接口,这里采用了动态代理,如果在View层显示数据之前用户可能退出了View层的页面,返回null的话,onSuccess()方法不会执行
                if (mView == null) {
                    return null;
                }
                //每次调用View层接口的方法,都会执行这里
                return method.invoke(view, args);
            }
        });
        //用反射动态创建Model
        Type[] params = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
        try {

            mModel = (M) ((Class) params[1]).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解绑View
     */
    public void detach() {
        mView = null;
        mModel = null;
    }

    public V getView() {
        return mView;
    }

    public M getModel() {
        return mModel;
    }
}

  1. 单 View 多 Presenter 的优化

通过反射创建Presenter ,类似功能在 学习的 demo 项目中使用 模仿 xutils 来动态注入控件省去 findbyid

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        mPresenters = new ArrayList<>();
        //1 Activity ? ViewGroupMvpProxy ? Fragment?抽离 工具类抽出去,或者把每个代码copy
        //注入Presenter 通过反射(或者Dagger)
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                //创建注入
                Class<? extends BasePresenter> presenterClazz = null;
                try {
                    //获取这个类
                    presenterClazz = ( Class<? extends BasePresenter> ) field.getType();
                } catch (Exception e) {
                    throw new RuntimeException("not support inject presenter" + field.getType());
                }
                try {
                    //创建BasePresenter对象
                    BasePresenter basePresenter = presenterClazz.newInstance();
                    //attach
                    basePresenter.attach(this);
                    mPresenters.add(basePresenter);
                    field.setAccessible(true);
                    field.set(this, basePresenter);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        initView();
        initData();
    }

测试用数据,可通过 charles 拦截返回

{
  "code": "200",
  "data": {
    "userName": "zhoubk",
    "userSex": "man",
    "id": 1
  },
  "msg": "success"
}

完整项目代码 github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值