基於AOP的MVP框架(一)GoMVP的使用

什麼是AOP?

在講解GoMVP框架的使用以前,咱們先了解一下什麼是AOP。android

面向切面編程

AOP —— Aspect Oriented Program,即面向切面編程,面向切面編程是一種思想,如同面向對象編程同樣,都是思想。編程

1、GoMVP的使用

一、添加依賴與插件

主工程中gradle添加:api

buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.2'
    }
}
複製代碼

app工程中gradle:緩存

apply plugin: 'com.android.application'
apply plugin: 'android-aspectjx'
複製代碼

app添加GoMVP依賴:網絡

dependencies {
    implementation 'com.wookii.gomvp:gomvp:1.3.2'
}
複製代碼

app添加AOP配置:架構

android{
    aspectjx {
        //AOP時,排除全部package路徑中包含`android.support`的class文件及庫(jar文件)
        exclude 'android.support'
    }
}
複製代碼

Demo

public class AnnotationDemoActivity extends AppCompatActivity {

    @BindView(R.id.button2)
    Button button;
    @BindView(R.id.button3)
    Button button3;

    @DataSource(RepositoryInjection.class)
    private LifecyclePresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_demo);
    }
    /**
     * test @GoBack
     * @param bean
     */
    @GoBack
    public void hahaha(MarketBean bean) {
        GoLog.E("MarketBean is backing:" + bean.getMessage());
    }
    @GoError
    public void error(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:
                break;
            case R.id.button3:
                presenter.execute(new MarketPresenterAdapter());
                break;
        }
    }
}
複製代碼

也許目前這個Demo片斷你們看起來難以消化,從它的一些註解能猜想到這是一個基於註解以及AOP實現的MVP框架,那麼接下來咱們一步步拆分,還原,介紹GoMVP的使用。app

二、初始化Retrofit

GoMVP的網絡請求框架是基於Retrofit,RxJava,OkHttp的網絡框架,爲了框架的靈活性,框架自己並不包含Retrofit的建立,這個須要外部提供,也就是使用者本身的Retrofit。建立好後,留着待用。框架

public class MainRetrofit implements RetrofitConverter {
    @Override
    public String host() {
        return ApiServer.URL_CONTRACT_NET;
    }

    @Override
    public Retrofit createRetrofit() {
        return XstoreRetrofitManager.getInstance().getRetrofit(host(), null);
    }
}
複製代碼

首先實現RetrofitConverter類,實現的第一個方法是指定網絡請求的host,第二個方法建立一個Retrofit而且create。這裏的XstoreRetrofitManager是使用者本身的。ide

三、初始化數據倉庫

在MVP架構中,數據倉庫是必不可少的組件(Repository),咱們先來建立它。post

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);
    }

    //綁定RetrofitConverter,很是關鍵
    @Override
    public RetrofitConverter onCreateRetrofitConverter() {
        return new MainRetrofit();
    }

    @Override
    public <T> void targetClazz(Class<T> clazz) {
        return MarketBean.class;
    }
}
複製代碼

做爲使用了GoMVP的Repository,必須實現GoDataSource接口,這個接口返回了四個方法功能以下:

一、loadDataFromRepository方法:

當presenter發起操做時,這是核心方法,治理返回了觀察者和被觀察者,發揮你的想象力能夠在這裏作一些業務邏輯的處理

二、getGoCache方法:

使用者須要在這裏返回一個緩存對象,默認使用由框架DefaultGoCache,後面會對緩存的擴展進行講解。

三、onCreateRetrofitConverter方法:

最爲關鍵,這個方法裏返回的就是咱們第二步建立的MainRetrofit對象,這樣數據倉庫和具體的Retrofit進行了綁定。

四、targetClazz方法:

會接收到一個class對象,這個class對象一般狀況下是個JavaBean,這是由使用者 去指定的,指定的地方在Presenter中,有些時候請求返回的Bean並非咱們想要的,能夠經過指定的bean作業務上的強轉,仍是看具體業務你用不用的上了。

四、建立Presenter擴展

在傳統的設計中Presenter的擴展都是經過繼承來完成的,在GoMVP中摒棄了這樣的方式,是經過PresenterAdapter去進行擴展(若是看到這裏比較迷糊,下一先跳過這一部分看一下示例再反過頭來看這部份內容)。

public class MarketPresenterAdapter extends PresenterAdapter{
    @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;
    }
}
複製代碼

依舊是四個方法,咱們分別解讀一下他們的做用

一、onCreateObservable方法:

該方法須要咱們建立一個Observable對象,這個對象會在咱們第三步建立的Repostory裏返回,方法體提供了一個RetrofitConverter對象,用來建立Observable,而這個RetrofitConverter是咱們第二步建立出來,第三部綁定的。

二、targetBeanType方法

這個方法很關鍵,上面說到Repository的targetClazz方法會返回一個class,就是由這個方法指定的,除此以外它還有個更關鍵的功能,我下面再說。

其餘兩個onSuccessCodePair和onErrorMessageKey方法如今用不到,後面再講。

五、使用示例

前面準備了怎麼多,咱們開始使用。

/**
 * Demo
 */
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 MarketRepository());
    }

    @GoBack
    public void hahaha(MarketBean bean) {
        GoLog.E("MarketBean is backing:" + bean.getValue().getMarketData().getAmountRtv());
    }
    
    @GoError
    public void error(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:
                break;
        }
    }
}
複製代碼

六、使用@Presenter註解初始化Presenter

一、任意一個類型爲LifecyclePresenter 的成員變量加上@Presenter註解,在Activity的onCreate時就會被建立好。

@Presenter
private LifecyclePresenter presenter;
複製代碼

PS:之因此叫作LifecyclePresenter,是由於它具備生命週期感知功能,無需使用者關心生命週期的問題,好比釋放Presenter,同時它內部集成了BKnife,默認會管理BKnife的初始化與解除綁定等與生命週期相關的操做(使用者在本身的工程添加BKnife的依賴便可)。

二、在onCreate中綁定數據倉庫

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_simple_demo);
    //綁定數據倉庫
    presenter.setRepository(new MarketRepository());
}
複製代碼

經過new的方式初始化MarketRepository是不優雅的,不建議這樣作,真正的作法是使用RepositoryInjection:下一節見。

相關文章
相關標籤/搜索