咱们接着上一节的内容继续:GoMVP(一)基于AOP的MVP框架GoMVP的使用json
经过new的方式初始化MarketRepository是不优雅的,不建议这样作,真正的作法是使用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方法执行操做: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
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
public void error(String errorMsg) {
GoLog.E("error is backing:" + errorMsg);
}
复制代码
@GoError是用来接收异常或者业务错误的注解,接收方法名能够任意起名,可是参数必定是一个String类型。code
咱们改一下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也会接收到。
在扩展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这个接口,咱们下一节介绍“拦截”。