基於AOP的MVP框架(三)GoMVP進階註解

上一節咱們將了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

有一種場景,若是一個頁面的多個接口調用返回的數據類型是一致的,咱們想單獨處理每個請求,咱們可使用@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。

六、使用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的回調都會被執行,注意。

七、擴展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接口,好比要實現本身的緩存方案,能夠這樣:

一、實現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

在Fragment中同樣可使用,這裏就不單獨寫例子了,但須要注意的是,若是使用註解初始化presenter,presenter只能夠在onCreateView的方法內以及其後的生命週期使用,以前好比onCreate中使用就會被報空指針異常,那是由於presenter沒有初始化的緣由,框架會在Fragment的onCeateView方法中初始化presenter。

基於AOP的實現原理

上面介紹了GoMVP的使用方式,咱們姐下來介紹它是如何作到只用一行註解就能夠完成Presenter的初始化和Repository的初始化與綁定,如何經過一行註解接收數據而不須要經過業務代碼去實現,這裏就要提到一個AOP的工具AspectJ,關於AspectJ的使用網上有不少的例子好比這一篇 www.jianshu.com/p/f90e04bcb… ,你們能夠先了解一下AspectJ的基本使用。

GoMVP源碼地址:github.com/wuchengithu…

結語:

GoMVP是一個基於AOP的MVP框架,在開發過程當中能夠減小模版代碼的書寫,提升開發效率的同時也具有着MVP架構的擴展性,同時框架也在探索更多的AOP特性,會不斷的進行優化和迭代。下面幾章將會介紹GoMVP的實現原理。

相關文章
相關標籤/搜索