转载

GoMVP(三)GoMVP的进阶注解

上一节我们将了GoMVP的进阶使用: GoMVP(二)GoMVP的进阶注解

如果想在框架处理返回数据之前对数据“动手脚”,我们可以在我们自己的PresenterAdapter上实现InterceptGoBack这个接口,我们拿上面的MarketPresenterAdapter举个例子:

4、"拦截"返回数据,优先处理

public class MarketPresenterAdapter extends PresenterAdapter implements InterceptGoBack<MarketBean>{
    @Override
    public Observable onCreateObservable(Context context, RetrofitConverter retrofitConverter) {
    
        Retrofit retrofit = retrofitConverter.createRetrofit();
        ApiServer apiServer = retrofit.create(ApiServer.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("请求参数1",0);
        map.put("请求参数2","123");
        Observable<HttpResult<SecretKeyBean>> observable = apiServer.getSecretKey(map);
        return observable;
    }

    @Override
    public Pair onSuccessCodePair() {
        return new Pair("success","true");
    }

    @Override
    public String onErrorMessageKey() {
        return "message";
    }

    @Override
    public Class targetBeanType() {
        return MarketBean.class;
    }
    
    @Override
    public boolean intercept(MarketBean marketBean) {
        //预先处理marketBean
        marketBean.setMessage("我被处理过了");
        return false;
    }
}
复制代码

实现InterceptGoBack接口后,还要实现一下它的intercept方法,方法的回调参数是你想要预先处理的JavaBean,这里是MarketBean,它的返回值很关键,

如果返回false,说明不会拦截流程继续交给框架去处理,View层会接收到回调,如果返回true,证明此处要拦截剩下的流程,不在交由框架去处理和返回到View层。

第二点需要注意的是,intercept处理完的Bean数据后,如果接着交给框架继续处理(返回false),框架会用处理过的数据继续执行剩下的逻辑。

5、使用@GoActionBack

有一种场景,如果一个页面的多个接口调用返回的数据类型是一致的,我们想单独处理每一个请求,我们可以使用@GoActionBack注解来接收回调:

public class AnnotationDemoActivity extends AppCompatActivity implements ExecuteStatusView {

    private static final String DELETE = "action_delete";
    private static final String ADD = "action_add";
    @BindView(R.id.button2)
    Button button;
    @BindView(R.id.button3)
    Button button3;

    /**
     * 注入Presenter,RepositoryInjection,
     * RepositoryInjection必须为DataSourceInjection的子类
     */
    @DataSource(RepositoryInjection.class)
    private LifecyclePresenter presenter;

    private MessageCountPresenter messagePresenterAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_demo);

        messagePresenterAdapter = new MessageCountPresenter();
        messagePresenterAdapter.setStatus(0);
        presenter.registerExecuteStatus(this);
    }
    /**
     * test @GoBack
     * @param bean
     */
    @GoBack
    public void hahaha(MarketBean bean) {
        GoLog.E("MarketBean is backing:" + bean.getMessage());
    }
    /**
     * 这里的action要对应Adapter里的action
     * test @GoActionBack
     * @param bean
     */
    @GoActionBack(action = DELETE)
    public void receiverDeleteData(MarketBean bean) {
        GoLog.E("MarketBean delete is backing:" + bean);
    }
    @GoActionBack(action = ADD)
    public void receiverAddData(MarketBean bean) {
        GoLog.E("MarketBean add is backing:" + bean);
    }
    
    @OnClick({R.id.button2, R.id.button3})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.button2:
                new Thread(() -> {
                    presenter.bindPresenterAdapter(new MarketPresenterAdapter(DELETE));
                    presenter.execute();
                }).start();
                break;
            case R.id.button3:
                presenter.execute(new MarketPresenterAdapter(ADD));
                break;
        }
    }
}
复制代码

上面的例子中,我们增加来三个回调方法,这三个回调的参数都是同一个类型MarketBean,其中两个使用了@GoActionBack注解,改注解参数是个字符串类型。同时在执行adapter时,给adapter传递了一个值,这个值就是注解上定义的字符串的值,这个值需要在adapter中使用,像这样:

public class MarketPresenterAdapter extends BasePresenterAdapter implements InterceptGoBack<MarketBean>{
    private String action;
    .
    .
    
    public MarketPresenterAdapter(String action) {
       this.action = action;
    }

    //if action 为null或者"",则被@GoActionBack修饰的方法接收不到回调。
    @Override
    public String action() {
        return action;
    }
    .
    .
}
复制代码

实现action方法,告诉框架这个Adapter和具体的接收事件的方法之间的关系,这样在框架执行完任务后才能找到正确的回调方法。比如:

presenter.execute(new MarketPresenterAdapter(ADD));
复制代码

当,执行完成后,该方法会收到回调:

@GoActionBack(action = ADD)
public void receiverAddData(MarketBean bean) {
    GoLog.E("MarketBean add is backing:" + bean);
}
复制代码

PS:注意上面三个回调方法,其中两个分别被@GoActionBack(action = ADD)与,@GoActionBack(action = DELETE)修饰,它们相对于使用了不同的action的Adapter,其中还有一个被@GoBack修饰的回调,这个回调的类型同样是MarketBean,所以不管使用那种action的Adapter,这个方法都会收到回调,因为@GoBack只认类型。而@GoActionBack多了层维度,不只认类型,还认action。

6、使用OnExecuteListener监听excute状态

实现ExecuteStatusView接口便可以监听excute执行状态

public class AnnoDemoActivity extends AppCompatActivity implements ExecuteStatusView {

    @DataSource(RepositoryInjection.class)
    private LifecyclePresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_demo);
        //注册进度监听
        presenter.registerExcuteStatus(this);
    }
    
    @Override
    public void onExecuteBegin() {
        //loading View show。。。
    }

    @Override
    public void onExecuteFinish() {
        //loading View close。。。
    }
    //其他代码。。。
}
复制代码

目前只提供了开始和结束,分别为onExecuteBegin和onExecuteFinish,同时需要注意的是,如果多次执行excute方法,每执行一次excute,ExecuteStatusView的回调都会被执行,注意。

7、扩展Cache

在初始化MarketRepository时,需要实现GoDataSource接口,其中getGoCache的返回值用来指定数据仓库的具体缓存实现:

public class MarketRepository implements GoDataSource {

    @Override
    public <B> GoDataSource loadDataFromRepository(Observable<B> observable, Observer observer) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
        return this;
    }

    /**
    * 指定具体缓存方案
    **/
    @Override
    public GoCache getGoCache(Context context) {
        return new DefaultGoCache(context);
    }

    @Override
    public RetrofitConverter onCreateRetrofitConverter() {
        return new MainRetrofit();
    }

    @Override
    public <T> void targetClazz(Class<T> clazz) {

    }
}
复制代码

在getGoCache方法返回了一个DefaultGoCache对象,这是框架提供的缓存实现,它实现了GoDataSource.GoCache接口,比如要实现自己的缓存方案,可以这样:

1、实现GoDataSource.GoCach接口

public class MyGoCache implements GoDataSource.GoCache<String, String> {

    private final Context context;

    public MyGoCache(Context context) {
        this.context = context;
    }

    @Override
    public void onAdd(String key, String value) {
        SharedPUtil.setParam(context, key, value);
        GoLog.D(TAG + "cache :" + "key:" + key + "....value:" + value);
    }

    @Override
    public String onGet(String key) {

        String s = SharedPUtil.getParam(context, key);
        GoLog.D(TAG + "cache out :" + "key:" + key + "....value:" + s);
        return s;
    }
}
复制代码

2、这里需要实现两个方法,一个onAdd,一个onGet,分别对应添加和获取,这里我们用SharedPreferences来作为缓存方案。

3、在实现我们自己的Repository时,把自定义的MyGoCache设置到我们的Repository里:

/**
        * 指定具体缓存方案
        **/
        @Override
        public GoCache getGoCache(Context context) {
            //自定义的GoCache/
            return new MyGoCache(context);
        }
复制代码

8、Fragment

在Fragment中一样可以使用,这里就不单独写例子了,但需要注意的是,如果使用注解初始化presenter,presenter只可以在onCreateView的方法内以及其后的生命周期使用,之前比如onCreate中使用就会被报空指针异常,那是因为presenter没有初始化的原因,框架会在Fragment的onCeateView方法中初始化presenter。

基于AOP的实现原理

上面介绍了GoMVP的使用方式,我们姐下来介绍它是如何做到只用一行注解就可以完成Presenter的初始化和Repository的初始化与绑定,如何通过一行注解接收数据而不需要通过业务代码去实现,这里就要提到一个AOP的工具AspectJ,关于AspectJ的使用网上有很多的例子比如这一篇 www.jianshu.com/p/f90e04bcb… ,大家可以先了解一下AspectJ的基本使用。

原文  https://juejin.im/post/5bb042e06fb9a05cd97316ac
正文到此结束
Loading...