基於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這個接口,咱們下一節介紹「攔截」。

相關文章
相關標籤/搜索