上一节咱们将了GoMVP的进阶使用:基于AOP的MVP框架(二)GoMVP进阶注解git
若是想在框架处理返回数据以前对数据“动手脚”,咱们能够在咱们本身的PresenterAdapter上实现InterceptGoBack这个接口,咱们拿上面的MarketPresenterAdapter举个例子:github
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,它的返回值很关键,api
若是返回false,说明不会拦截流程继续交给框架去处理,View层会接收到回调,若是返回true,证实此处要拦截剩下的流程,不在交由框架去处理和返回到View层。缓存
第二点须要注意的是,intercept处理完的Bean数据后,若是接着交给框架继续处理(返回false),框架会用处理过的数据继续执行剩下的逻辑。bash
有一种场景,若是一个页面的多个接口调用返回的数据类型是一致的,咱们想单独处理每个请求,咱们可使用@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和具体的接收事件的方法之间的关系,这样在框架执行完任务后才能找到正确的回调方法。好比:ide
presenter.execute(new MarketPresenterAdapter(ADD));
工具
当,执行完成后,该方法会收到回调:post
@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。
实现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的回调都会被执行,注意。
在初始化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接口,好比要实现本身的缓存方案,能够这样:
一、实现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;
}
}
复制代码
二、这里须要实现两个方法,一个onAdd,一个onGet,分别对应添加和获取,这里咱们用SharedPreferences来做为缓存方案。
三、在实现咱们本身的Repository时,把自定义的MyGoCache设置到咱们的Repository里:
/**
* 指定具体缓存方案
**/
@Override
public GoCache getGoCache(Context context) {
//自定义的GoCache/
return new MyGoCache(context);
}
复制代码
在Fragment中同样可使用,这里就不单独写例子了,但须要注意的是,若是使用注解初始化presenter,presenter只能够在onCreateView的方法内以及其后的生命周期使用,以前好比onCreate中使用就会被报空指针异常,那是由于presenter没有初始化的缘由,框架会在Fragment的onCeateView方法中初始化presenter。
上面介绍了GoMVP的使用方式,咱们姐下来介绍它是如何作到只用一行注解就能够完成Presenter的初始化和Repository的初始化与绑定,如何经过一行注解接收数据而不须要经过业务代码去实现,这里就要提到一个AOP的工具AspectJ,关于AspectJ的使用网上有不少的例子好比这一篇 www.jianshu.com/p/f90e04bcb… ,你们能够先了解一下AspectJ的基本使用。
GoMVP是一个基于AOP的MVP框架,在开发过程当中能够减小模版代码的书写,提升开发效率的同时也具有着MVP架构的扩展性,同时框架也在探索更多的AOP特性,会不断的进行优化和迭代。下面几章将会介绍GoMVP的实现原理。