上一節咱們將了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的實現原理。