自定义注解在MVP中的使用

在Mvp架构中Activity需要创建Presenter对象,并处理与Presenter的绑定、解除绑定关系,这是View层公共的逻辑,可以把这些逻辑抽取到Base中统一处理,然而一个Activity中可能需要创建多个Presenter对象,这就需要在Activity中创建一个List列表来存储这个页面中所有的Presenter对象,在具体的子类Activiy中并不确定到底有多少个Presenter对象,解决这个问题可以为子类提供一个抽象方法,通过实现这个抽象方法子类Activity将所有创建的Presenter对象手动添加进去,这样操作起来会有点麻烦,而且在实际编码过程中还经常会忘记这步操作。这里通过自定义注解的方式来解决这个问题,具体就是通过为Presenter变量添加注解,在基类中解析注解信息自动创建Presenter对象、自动维护List列表和相关逻辑,做到子类完全不用关心这些操作,下面看下代码实现:

1、创建自定义注解类

package com.znh.commonlib.base.inject;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by znh on 2019/6/3
 */
@Target(ElementType.FIELD) //注释1
@Retention(RetentionPolicy.RUNTIME) //注释2
public @interface InjectPresenter {

}

上述代码就定义了一个注解InjectPresenter,注释1代表该注解作用于成员变量,注释2代表该注解是运行时注解。

2、创建基类BaseMvpActivity处理相关逻辑

package com.znh.commonlib.base;

import android.os.Bundle;
import android.support.annotation.Nullable;

import com.znh.commonlib.base.inject.InjectPresenter;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by znh on 2019/6/3
 * <p>
 * MvpActivity基类
 */
public abstract class BaseMvpActivity extends RxAppCompatActivity implements IBaseView {

    //存储当前页面中对应的所有的Presenter
    public List<BasePresenter> mPresenters;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());

        //处理Presenter的创建和绑定
        mPresenters = new ArrayList<>();
        createAndBindPresenter();

        initView();
        initData();
    }

    /**
     * 获取页面布局id
     *
     * @return
     */
    public abstract int getLayoutId();

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

    /**
     * 初始化数据
     */
    protected abstract void initData();

    /**
     * 创建并绑定Presenter
     */
    public void createAndBindPresenter() {
        //通过反射注入Presenter
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
            	//注释3
                if (!BasePresenter.class.isAssignableFrom(field.getType())) {
                    throw new RuntimeException("InjectPresenter annotations have incorrect field types and can only be used for BasePresenter and its subclasses");
                }
                Class<? extends BasePresenter> basePresenterClazz = (Class<? extends BasePresenter>) field.getType();

                try {
                    //注释4 创建对象
                    BasePresenter basePresenter = basePresenterClazz.newInstance();
                    basePresenter.attachView(this);

                    //设置字段
                    field.setAccessible(true);
                    field.set(this, basePresenter);

                    //注释5 添加Presenter
                    mPresenters.add(basePresenter);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 解绑Presenter
     */
    public void unBindPresenter() {
        for (BasePresenter basePresenter : mPresenters) {
            basePresenter.detachView();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unBindPresenter();
    }
}

在onCreate方法中创建mPresenters列表用来存储页面中所有的Presenter对象,然后调用createAndBindPresenter方法创建页面中所有的Presenter对象,并处理绑定逻辑,在注释3处校验注解作用的字段是否是BasePresenter类型的,如果不是就抛出异常,注释4处通过反射创建出Presenter实例对象并和View进行绑定,注释5处将创建的Presenter实例对象添加到集合列表中进行管理。在Activity的onDestroy方法中调用unBindPresenter方法对所有跟这个Activity有绑定关系的Presenter进行解除绑定,防止内存泄漏。

3、在代码中直接使用注解

package com.znh.commonlib.base;

import com.znh.commonlib.base.inject.InjectPresenter;

/**
 * Created by znh on 2019/6/3
 * <p>
 * 测试页面
 */
public class TestActivity extends BaseMvpActivity {

    @InjectPresenter
    private Presenter1 mPresenter1;

    @InjectPresenter
    private Presenter2 mPresenter2;

    @InjectPresenter
    private Presenter3 mPresenter3;
    
    public void loadData() {
        mPresenter1.loadData();
        mPresenter2.loadData();
        mPresenter3.loadData();
    }

	...........
}

在Activity子类中如果需要使用哪个Presenter,就直接将对应的Presenter声明为成员变量并为其添加@InjectPresenter注解,就可以直接在代码中调用对应Presenter的方法,不需要关心其他的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章