GoMVP(三)GoMVP的进阶注解

栏目: Java · 发布时间: 5年前

内容简介:上一节我们将了GoMVP的进阶使用:如果想在框架处理返回数据之前对数据“动手脚”,我们可以在我们自己的PresenterAdapter上实现InterceptGoBack这个接口,我们拿上面的MarketPresenterAdapter举个例子:实现InterceptGoBack接口后,还要实现一下它的intercept方法,方法的回调参数是你想要预先处理的JavaBean,这里是MarketBean,它的返回值很关键,

上一节我们将了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的基本使用。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Eric Meyer on CSS

Eric Meyer on CSS

Eric Meyer / New Riders Press / 2002-7-8 / USD 55.00

There are several other books on the market that serve as in-depth technical guides or reference books for CSS. None, however, take a more hands-on approach and use practical examples to teach readers......一起来看看 《Eric Meyer on CSS》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具