1. 程式人生 > >Rxjava2.x 封裝總結

Rxjava2.x 封裝總結

封裝作為java的三大特性之一,相信每個開發者對封裝技術點都能說出一些,但是真正到專案實際開發,很多開發者都沒有注意,今天這篇部落格主要總結一下rxjava2.0使用過程中一些封裝。

一、執行緒排程封裝

先上一段簡單的程式碼,比較常見。

Flowable.timer(3000, TimeUnit.MILLISECONDS)
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(new
Consumer<Long>() { @Override public void accept(Long aLong) throws Exception { } });

上面這段程式碼只是簡單做了一下延遲,很常見的寫法,這個應該怎麼樣優化呢?大家有沒有注意執行緒排程這裡,每個介面幾乎有執行緒排程相關的操作,這裡可不可以封裝一下呢??答案是可以的

/**
     * 統一執行緒處理
     * @param <T>
     * @return
*/
public static <T> FlowableTransformer<T, T> rxSchedulerHelper() { //compose簡化執行緒 return new FlowableTransformer<T, T>() { @Override public Flowable<T> apply(Flowable<T> observable) { return observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }; }

通過使用使用compose()操作符,compose()裡接收一個FlowableTransformer物件,FlowableTransformer是個介面,通過實現這個介面,將FlowableTransformer轉化成 Publisher,接下來上面倒計時那段程式碼就可以寫成這個樣子

Flowable.timer(3000, TimeUnit.MILLISECONDS)
//                  .subscribeOn(Schedulers.io())
//                  .observeOn(AndroidSchedulers.mainThread())
                    .compose(RxUtil.<Long>rxSchedulerHelper())
                    .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {

                    }
                });

二、UI、異常相關封裝

我們平時網路請求的的程式碼中,大概的套路都是這樣,發請網路請求後,在頁面上彈個正在載入的頁面,請求成功或者失敗後取消正在載入的頁面,展示相應的頁面。比較笨的方法,每次請求在onStart()中展示進度,onNext()onComplete或取消,展示頁面,其實也沒毛病,就是程式碼重複率太高,效率低,接下來我們把這個操作簡單的封裝一下。

public abstract class CommonSubscriber<T> extends ResourceSubscriber<T> {
    private BaseView mView;
    private String mErrorMsg;
    private boolean isShowErrorState = true;

    protected CommonSubscriber(BaseView view){
        this.mView = view;
    }

    @Override
    public void onError(Throwable e) {
        if (mView == null) {
            return;
        }
        if (mErrorMsg != null && !TextUtils.isEmpty(mErrorMsg)) {
            mView.showErrorMsg(mErrorMsg);
        } else if (e instanceof ApiException) {
            mView.showErrorMsg(e.toString());
        } else if (e instanceof HttpException) {
            mView.showErrorMsg("資料載入失敗");
        } else {
            mView.showErrorMsg("未知錯誤");
        }
        if (isShowErrorState) {
            mView.stateError();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
         mView.stateLoading();
    }

    @Override
    public void onComplete() {
        mView.stateMain();
    }
}

這裡我簡單的解釋一下,BaseView用於處理View相關的狀態的介面,具體寫法看自己的業務需求,不多解釋。重點看一下ResourceSubscriber這個類,檢視原始碼我們發現此類實現了FlowableSubscriber, Disposable,主要功能是 允許非同步取消其訂閱相關資源,節省記憶體而且是執行緒安全。這樣我們就可以在subscribeWith(這個方法可以返回當前訂閱的觀察者)中使用自定義這個類了。

 Flowable.timer(3000, TimeUnit.MILLISECONDS)
                .compose(RxUtil.<Long>rxSchedulerHelper())
                .subscribeWith(new CommonSubscriber<Long>(this) {
                    @Override
                    public void onNext(Long aLong) {
                        Log.e(TAG, "accept: 三秒後執行");
                    }
                });

我在CommonSubscriber類中,onStart和onComplete方法中分別打了一個log,輸出如下;
這裡寫圖片描述
有圖有真相,跟我們預想中的一樣,所以我在開發中只需關注onNext()中資料相關的就可以了。

三、伺服器返回資料統一封裝

我們在平時開發中,後臺返回的資料格式都應該一致的(除非你們公司後臺是剛畢業的實習生),比較常見的介面返回型別如下,目前我們公司後臺資料格式就是這個,當然別的型別也沒毛病,大同小異。

    private int code;
    private String message;
    private T data;

通過code判斷是否是成功與否,錯誤資訊封裝在message中,data就是我們最終關心的資料,正常情況我們一般這麼做,我簡單寫個虛擬碼:

 if(data.getCode() == 200) {
       return code;
     } else {
        return message;
     }

以上這段程式碼幾乎每個網路請求都要這麼寫,甚至還要判斷data不為空,蜜汁縮排,我們View中最關心的是展示給使用者的資料(data)及當發生錯誤時候展示給使用者的提示(message),view(mvp模式中 presenter)並不需要知道怎麼來的,接下來我就針對這個情況封裝一下。

 /**
     * 統一返回結果處理
     * @param <T>
     * @return
     */
    public static <T> FlowableTransformer<MyHttpResponse<T>, T> handleMyResult() {   //compose判斷結果
        return new FlowableTransformer<MyHttpResponse<T>, T>() {
            @Override
            public Flowable<T> apply(Flowable<MyHttpResponse<T>> httpResponseFlowable) {
                return httpResponseFlowable.flatMap(new Function<MyHttpResponse<T>, Flowable<T>>() {
                    @Override
                    public Flowable<T> apply(MyHttpResponse<T> tMyHttpResponse) {
                        if(tMyHttpResponse.getCode() == 200) {
                            return createData(tMyHttpResponse.getData());
                        } else {
                            return Flowable.error(new ApiException(tMyHttpResponse.getMessage(), tMyHttpResponse.getCode()));
                        }
                    }
                });
            }
        };
    }

createData()

/**
     * 生成Flowable
     * @param <T>
     * @return
     */
    public static <T> Flowable<T> createData(final T t) {
        return Flowable.create(new FlowableOnSubscribe<T>() {
            @Override
            public void subscribe(FlowableEmitter<T> emitter) throws Exception {
                try {
                    emitter.onNext(t);
                    emitter.onComplete();
                } catch (Exception e) {
                    emitter.onError(e);
                }
            }
        }, BackpressureStrategy.BUFFER);
    }

接下來,在我們程式碼中就可以這樣搞了,上面的例子不適用這個了,我截取了一段我們專案中判斷當前版本號的程式碼,如下

 apiService.appversion(test1, test2)            
                .compose(RxUtil<MyHttpResponse <VersionBean>>rxSchedulerHelper())
                .compose(RxUtil.<VersionBean>handleMyResult())
                .//省略

以上就是我對Rxjava的簡單封裝,並且已經在專案中實際使用過,使用起來比較舒服,省去很多囉嗦的程式碼。各位讀者發現有什麼錯誤或者有更好的建議,請在下面評論指出,謝謝!