基于AOP的MVP框架(二)GoMVP进阶注解

咱们接着上一节的内容继续:GoMVP(一)基于AOP的MVP框架GoMVP的使用json

经过new的方式初始化MarketRepository是不优雅的,不建议这样作,真正的作法是使用RepositoryInjection:网络

七、RepositoryInjection

public class RepositoryInjection implements DataSourceInjection {
    @Override
    public GoDataSource provideRepository(@NonNull Context context) {
        checkNotNull(context);
        return new MarketRepository()
    }
}
复制代码

GoMVP提供了一个DataSourceInjection,经过实现DataSourceInjection来建立一个RepositoryInjection,上面onCreate方法内应该这样写:框架

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_simple_demo);
    //绑定数据仓库
    presenter
    .setRepository(new RepositoryInjection().provideRepository(getApplicationContext()));
}
复制代码

框架支持注解建立Repository,前提是必需要用DataSourceInjection这个接口,咱们下面会讲到。ide

八、execute()

使用execute方法执行操做:post

@OnClick({R.id.button2, R.id.button3})
public void onViewClicked(View view) {
    switch (view.getId()) {
        case R.id.button2:
            presenter.execute(new MarketPresenterAdapter());
            break;
        case R.id.button3:
            break;
    }
}
复制代码

execute的入参是一个PresenterAdapter。spa

九、使用@GoBack注解接受数据

@GoBack
public void hahaha(MarketBean bean) {
    GoLog.E("MarketBean is backing:" + bean.getValue().getMarketData().getAmountRtv());
}
复制代码

在Activity任意名称的方法体上加上@GoBack就能够接收数据了,接收什么数据,参数就要指定成什么类型,好比这里接收的是MarketBean,若是你在这里随便写个什么其余类型这个方法是不会被回调的,为何呢,由于咱们在执行presenter的excute方法传入的是MarketPresenterAdapter对象,它指定了类型,返回头看看MarketPresenterAdapter这个类的targetBeanType方法指定的类型是什么?没错就是MarketBean,若是你想接收MarketPresenterAdapter的数据,就要与它相呼应。指针

@Override
    public <T> void targetClazz(Class<T> clazz) {
        return MarketBean.class;
    }
复制代码

十、使用@GoError接收异常错误信息

@GoError
    public void error(String errorMsg) {
        GoLog.E("error is backing:" + errorMsg);
    }
复制代码

@GoError是用来接收异常或者业务错误的注解,接收方法名能够任意起名,可是参数必定是一个String类型。code

2、进阶使用

一、使用@DataSource注解注入Repository

咱们改一下presnter变量的注解为这样:对象

@DataSource(RepositoryInjection.class)
private LifecyclePresenter presenter;
复制代码

@DataSource注解的参数是一个DataSourceInjection类型的class,经过这个注解presenter的建立与Repository的注入一鼓作气,因此在onCreate方法中就不须要写绑定的代码了。token

public class AnnoDemoActivity extends AppCompatActivity{

    
    @DataSource(RepositoryInjection.class)
    private LifecyclePresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_demo);
        //不须要绑定数据仓库的代码了
        
        messagePresenterAdapter = new MessageCountPresenter();
        messagePresenterAdapter.setStatus(0);
    }
    //其余代码。。。
}
复制代码

Note:若是同时存在@Presenter和@DataSource这两个注解的变量,@DataSource注解的变量会生效,若是调用了presenter的setRepository,最后set的Repository会生效。

二、一个界面接收多个返回

有的时候,一个界面可能由多个接口数据组成,咱们这里有两个PresenterAdapter,MarketPresenterAdapter和MessageCountPresenter,分别获取市场信息和消息个数,如何在Activity里接收呢?

咱们在上面已经指定了MarketPresenterAdapter的targetClazz,如今咱们指定MessageCountPresenter

public class MessageCountPresenter extends BasePresenterAdapter {

    //略去部分代码……

    @Override
    public Class targetBeanType() {
        return NoticeCountBean.class;
    }
}
复制代码

那么接收的时候能够这么写了:

public class AnnoDemoActivity extends AppCompatActivity{

    @BindView(R.id.button2)
    Button button;
    @BindView(R.id.button3)
    Button button3;
    
    @Presenter()
    private LifecyclePresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_demo);
        //绑定数据仓库
         presenter
            .setRepository(new RepositoryInjection().provideRepository(getApplicationContext()));
        
        messagePresenterAdapter = new MessageCountPresenter();
        messagePresenterAdapter.setStatus(0);
    }
    //接收市场数据
    @GoBack
    public void hahaha(MarketBean bean) {
        GoLog.E("MarketBean is backing:" + bean.getValue().getMarketData().getAmountRtv());
    }
    //接收消息个数数据
    @GoBack
    public void receiverData(NoticeCountBean bean) {
        GoLog.E("NoticeCountBean is backing:" + bean);
    }
    //接收全部的异常返回
    @GoError
    public void error(String errorMsg) {
        GoLog.E("error is backing:" + errorMsg);
    }
    
    //接收消息个数数据异常返回
    @GoError
    public void errorNoticeCount(NoticeCountBean bean,String errorMsg) {
        GoLog.E("error is backing:" + errorMsg);
    }
    
    @OnClick({R.id.button2, R.id.button3})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.button2:
                presenter.execute(new MarketPresenterAdapter());
                break;
            case R.id.button3:
                presenter.execute(messagePresenterAdapter);
                break;
        }
    }
}
复制代码

方法hahaha和方法receiverData分别接收MarketBean和NoticeCountBean,接收什么实例和方法名无关,只于方法参数的具体类型有关。

一样的,不一样的execute操做会返回不一样的异常错误信息,若是不单独指定,上面的error方法能够接收它们全部的异常,但有种状况,可能会针对不一样的execute处理不一样的异常,这种状况下就须要使用类型肯定了,和接收同样,增长一个包含类型的参数方法,好比errorNoticeCount方法,这个方法的第一个参数是NoticeCountBean对象,这样经过@GoError这个注解,就能够接收到NoticeCount的错误异常,而只会接收到NoticeCount形成的业务异常。

PS:须要注意的是,errorNoticeCount接收的只是业务上的错误,好比token失效这样的。若是碰到相似与(IO,超时,null指针,Json解析等)这样的异常,只会在error里返回,不会在errorNoticeCount返回。而error会接收全部的错误和异常包括errorNoticeCount返回的业务异常error也会接收到。

三、Json预处理

在扩展Presenter,也就是PresenterAdapter时,有两个方法:

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

@Override
public String onErrorMessageKey() {
    return "message";
}
复制代码

框架中默认使用Json返回数据的格式,想象一下当一个数据返回时,咱们可能须要处理一下再使用,最多见的是业务层面的成功与失败,在定义的通常格式的json中最外层的属性里必定会有一个判断业务成功与失败的字段,好比successCode,responseCode等等,你把这个字段告诉框架,而且告诉框架这个字段表示成功的值是什么。这里的例子告诉框架,表示请求结果的成功或失败的字段名为"success",表示成功的值为"true",这样框架处理数据时,若是发现没有这个字段,或者有“success”这个字段但值不为"true"时(注意这里的值是个字符串的true,这是由于业务具体而定,也许是个整形的0,或者boolean的true),将会认为是个错误的请求,把结果经过@GoError标注的方法在Activity返回。

而onErrorMessageKey方法是用来肯定,当返回业务错误时,咱们须要解析哪一个字段来返回错误信息,好比当咱们执行一些敏感操做时,会携带token 去客户端作验证,若是token失效会返回一个错误码,若是返回字段中有错误信息字段,咱们能够直接告诉框架这个字段是什么,这里这个字段叫“message”,这样当框架发现success字段返回的不是“true”时,就会解析message字段,将错误提示内容,好比“token失效”经过@GoError修饰的方法返回。固然框架没法判断多种状况,若是觉的这两个方法没法知足使用者的业务需求,咱们还能够经过“拦截”返回数据,来处理多变的业务逻辑。

PS:若是不处理上面两个方法,会发生什么?

若是不处理上面两个方法,框架将不会关心业务异常,会把数据生成的JavaBean返回到View层,而处理异常的@GoError修饰的方法将不会收到业务异常,只会收到运行时的异常(好比IO,网络,解析json等这些异常)由于使用者并无定义。

若是想在框架处理返回数据以前对数据“动手脚”,咱们能够在咱们本身的PresenterAdapter上实现InterceptGoBack这个接口,咱们下一节介绍“拦截”。

相关文章
相关标签/搜索