AndroidMVP+Retrofit2+Rxjava2+Rxlifecycle2組合項目框架

描述:17年最火的安卓網絡框架無疑是Retrofit2.0+Okhttp3.0,而中型項目架構最火的無疑是MVP,而今年Rxjava2.0也是異常的火爆,而Rxlifecycle的支持對使用rxjava出現內存泄露問題得到完美解決,對此,之前樓主對這幾種很火的技術封裝過一次,現在根據業務增加,進行了二次封裝。文章後面有本框架github地址。

一、所用技術

/ MVP  點擊打開鏈接

/ Retrofit2.0 點擊打開鏈接     點擊打開鏈接

/ Okhttp3.0 點擊打開鏈接

/ Rxjava2.0 點擊打開鏈接

/ Rxlifecycle2.0 點擊打開鏈接

這裏就不細說這他們的基礎知識了,傳送門在上面。


二、架構

1.分包:目前demo裏面涉及到的包如下,如有其他的需求自定義包的名字就好,比如adapter包、custom包。

     

主要作用如下圖:


大家看到了上面這個多base想到了什麼,基類?抽象?接口?繼承?模版?答案是都對,不過還有一個沒說到,那就是泛型。java語言有泛型的支持我覺得是一件很棒的事情,有了它我相信很多人都不用手動去寫對象強轉了吧。

1.BaseView類

public interface BaseView {
    
}
它裏面爲空,沒有任何抽象方法,接口的作用有哪些還記得嗎?其中有一個作用就是標識作用,標識它是一個View的基類。

2.BasePersenter

public abstract class BasePresenter<V extends BaseView>{
    private V mView;

    public V getView(){
        return mView;
    }
    public void attachView(V v){
        mView = v;
    }
    public void detachView(){
        mView = null;
    }
}
其中泛型V繼承於BaseView,也就是說我們傳的V泛型是必須繼承BaseView的,不然代碼檢查報錯。我們可以看到attachView和detachView兩個方法,當我們的view需要的時候就綁定p層,view銷燬的時候就與p層解綁。

3.BaseModel

public class BaseModel<T> {
    /**
     * 封裝線程管理和訂閱的過程
     * flag  是否添加progressdialog
     */
    public void subscribe(Context context, final Observable observable, ObserverResponseListener<T> listener,
                          ObservableTransformer<T,T> transformer, boolean isDialog, boolean cancelable) {
        final Observer<T> observer = new ProgressObserver(context, listener, isDialog,cancelable);
        observable.compose(transformer)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    public void subscribe(Context context, final Observable observable, ObserverResponseListener<T> listener,
                          ObservableTransformer<T,T> transformer) {
        subscribe(context,observable,listener,transformer,true,true);
    }
}

BaseModel主要作用是封裝線程管理和訂閱的過程,當然也可以封裝數據庫的操作,這裏我就沒有寫出來了。

4.BaseApi:

主要是封裝網絡對象retrofit,裏面可以設置網絡的連接超時和讀取時間、日誌攔截、緩存攔截、頭文件攔截等等。

5.Api及ApiService:

主要管理api接口。

6.BaseActivity、BaseFragment



BaseActivity引用P和V,泛型有兩個,必須分別繼承與BaseView與BasePresenter。當子類activity繼承於BaseAcivity時,getLayoutId方法獲取綁定佈局,然後createPresenter方法創建出p層,並將v視圖綁定。然後調用的init方法,我們就可以將初始化數據放到這裏。在activity銷燬時,將p層與v視圖解綁。Fragment用法也相似。

7.progress包:

ObserverResponseListener:請求監聽成功或者失敗。

ProgressCancelListener:請求監聽取消時。

ProgressDialogHandler:dialog出現與隱藏的一個Handler。

ProgressObserver(觀察者):繼承與Observer,監聽請求是否成功,

public class ProgressObserver<T> implements Observer<T>, ProgressCancelListener {
    private static final String TAG = "ProgressObserver____ ";
    private ObserverResponseListener listener;
    private ProgressDialogHandler mProgressDialogHandler;
    private Context context;
    private Disposable d;

    public ProgressObserver(Context context, ObserverResponseListener listener, boolean isDialog, boolean cancelable) {
        this.listener = listener;
        this.context = context;
        if(isDialog){
            mProgressDialogHandler = new ProgressDialogHandler(context, this, cancelable);
        }
    }

    private void showProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
        }
    }

    private void dismissProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
            mProgressDialogHandler = null;
        }
    }

    @Override
    public void onSubscribe(Disposable d) {
        this.d = d;
        Log.e(TAG, "onSubscribe: ");
        showProgressDialog();
    }

    @Override
    public void onNext(T t) {
        listener.onNext(t);//可定製接口,通過code回調處理不同的業務
    }

    @Override
    public void onError(Throwable e) {
        dismissProgressDialog();
        Log.e(TAG, "onError: ", e);
        //自定義異常處理
        if(e instanceof ExceptionHandle.ResponeThrowable){
            listener.onError((ExceptionHandle.ResponeThrowable)e);
        } else {
            listener.onError(new ExceptionHandle.ResponeThrowable(e, ExceptionHandle.ERROR.UNKNOWN));
        }

        if (e instanceof UnknownHostException) {
            ToastUtil.showLongToast("請打開網絡");
        } else if (e instanceof SocketTimeoutException) {
            ToastUtil.showLongToast("請求超時");
        } else if (e instanceof ConnectException) {
            ToastUtil.showLongToast("連接失敗");
        } else if (e instanceof HttpException) {
            ToastUtil.showLongToast("請求超時");
        }else {
            ToastUtil.showLongToast("請求失敗");
        }
    }

    @Override
    public void onComplete() {
        dismissProgressDialog();
        Log.e(TAG, "onComplete: ");
    }

    @Override
    public void onCancelProgress() {
        Log.e(TAG, "requestCancel: ");
        //如果處於訂閱狀態,則取消訂閱
        if (!d.isDisposed()) {
            d.dispose();
        }
    }
}
上面已經很清楚了,在onNext方法裏面獲取到響應再調用ObserverResponseListener接口的onNext回調到相應的P層,在觀察者的onError方法裏面根據自定義異常類,回調ObserverResponseListener接口的onError方法。自定義異常處理類就不多說了,裏面很詳細。這個觀察者實現了ProgressCancelListener的onCancelProgress方法,也就是當我們點擊回退鍵取消請求時,會調用此方法,在這裏我們拿到將在onSubscribe時給我們的Disposable消費者對象取消消費事件,此時將不會下發事件到觀察者的onNext方法,實現取消訂閱。

到這裏,本框架基本就結束了。

下面講一下一個activity的例子:

1.創建契約類:爲什麼創建契約類?將一個業務所要用到的方法寫在一起不是便於管理嗎?以後需求增加或者改變,直接找契約類就行了。


V有三個方法:第一個是當數據請求成功時返回結果,第二個是失敗時發送信息通知界面,第三個是綁定完成Observable發佈的事件和當前組件綁定,實現生命週期同步,從而實現當前組件生命週期結束時,自動取消對Observable訂閱。

P有一個方法:設置請求參數及是否顯示dialog與該dialog是否能被取消。

2.創建實體類:這就不用說了。


3.創建model層:


我測試用的這個方法本來是想用我們公司的測試登錄接口的,但是可能會改變,所以我就用的一個開源查詢快遞的api,可以直接使用通用的請求方法,故此直接繼承BaseModel類,並調用subscribe這個方法即可。

4.創建Persenter層:


P層繼承契約類裏面寫好的抽象P層,實現其中的login抽象方法,在P層構造中實例化M層對象。當P層的login方法被調用時,M層調用它自己的login方法進行網絡請求。實現ObseriverResponseListener的請求成功與失敗方法。當觀察者走到了它的onNext方法時,它將會回調ObseriverResponseListener的onNext方法到P層,P層拿到數據結果,調用與之綁定的V層方法result傳值給頁面以更新數據,相應的onError方法也是如此理解即可。

5.activity頁面:



如圖所示:

頁面只需要繼承BaseActivity並傳入業務邏輯相關的契約類V和P,然後實現接口V的方法。

大家應該理解得到,首先設置佈局,創建該業務的P層實例,創建V層。然後就是等待按鈕點擊,調用P層的login方法,P層調用getview方法的bindlifecycle方法綁定生命週期,然後等待P層返回數據和Msg。

--->問題1:如何在一個頁面實現多個請求

1.在Contract層的Presenter建立抽象方法2


2.在Module層建立方法,在ApiService層建立相應的接口;


3.在Activity實現Contract層的接口;

在Activity調用getPresenter().logout(map2,false,true),完成頁面請求多個接口了。


--->問題2:業務量少的時候,不需要用P層的情況下,怎麼使用rx來管理請求

1.創建Activity後繼承BaseActivity,不需要傳入泛型等等;

2.實現BaseActivity的createPresenter、createView方法時返回null,此時也需要一個module層來提供網絡請求等的方法;

3.在Activity直接調用module層的方法進行請求即可。


以上例子是很簡單的,在實際項目過程中,業務邏輯肯定相對複雜的多,不過大致的網絡方面的問題基本上此框架即可完成。


閱讀到此,本文也結束了,有問題issues,希望能有star哦。因爲本人堅持開源原則,所以這裏只放了github。https://github.com/senonwx/mvpretrofitrx.git


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章