RxJava + Retrofit 的實際應用場景

介紹

關于RxJava Retrofit很多篇文章都有詳細的說明,在這里我想分享一個具體的使用案例,在我的開源項目 就看天氣 里的實際應用。也希望跟大家探討如何優(yōu)雅的使用。

前提

需要知道什么是 RxJava

這里推薦下 扔物線寫的 給 Android 開發(fā)者的 RxJava 詳解

再感謝 RxJava 與 Retrofit 結(jié)合的最佳實踐 這篇滿滿的干貨。

實戰(zhàn)

準備

項目中用到的依賴:

compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.google.code.gson:gson:2.4'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'com.squareup.okhttp3:okhttp:3.0.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
compile 'com.squareup.okio:okio:1.6.0'

因為要用到網(wǎng)絡,所以千萬別忘記了這個權(quán)限。

<uses-permission android:name="android.permission.INTERNET"/>

組件

Rx 封裝的工具

使用compose操作符

compose()里接收一個Transformer對象,Transformer繼承自Func1<Observable<T>, Observable<R>>,可以通過它將一種類型的Observable轉(zhuǎn)換成另一種類型的Observable。

RxSchedulerHelper

封裝 Rx 線程相關操作

public static <T> Observable.Transformer<T, T> rxSchedulerHelper() {
    return tObservable -> tObservable.subscribeOn(Schedulers.io())
        .unsubscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread());
}
handleResult

封裝 API 請求后統(tǒng)一處理

public static <T> Observable.Transformer<Result<T>, T> handleResult() {
    return resultObservable -> resultObservable.flatMap(tResult -> {
        if (tResult.code == 1) {
            return createData(tResult.data);
        } else {
            return Observable.error(new ApiException(tResult.code));
        }
    });
}

RetrofitSingleton

自己封裝了下 Retrofit??梢詫W習下小艾的方式

自己將請求是寫在該類,使用者只需要關心如何處理拿到的數(shù)據(jù)和相應的 UI 操作。

public Observable<Weather> fetchWeather(String city) {
    return apiService.mWeatherAPI(city, C.KEY)
        .filter(weatherAPI -> weatherAPI.mHeWeatherDataService30s.get(0).status.equals("ok"))
        .map(weatherAPI -> weatherAPI.mHeWeatherDataService30s.get(0))
        .compose(RxUtils.rxSchedulerHelper());
}

public Observable<VersionAPI> fetchVersion() {
    return apiService.mVersionAPI(C.API_TOKEN).compose(RxUtils.rxSchedulerHelper());
}

使用

網(wǎng)絡拉取讀取緩存用 Rx 結(jié)合。
這里就要使用 concat 操作符,官方解釋.

首先看看獲取網(wǎng)絡是如何寫的:

private Observable<Weather> fetchDataByNetWork() {
    String cityName = Util.replaceCity(mSetting.getCityName());
    return RetrofitSingleton.getInstance()
        .fetchWeather(cityName)
        .onErrorReturn(throwable -> {
            PLog.e(throwable.getMessage());
            return null;
        });
}

這里的 onErrorReturn 待會兒說。

再來看看讀取緩存的代碼:

private Observable<Weather> fetchDataByCache() {
    return Observable.defer(() -> {
        Weather weather = (Weather) aCache.getAsObject(C.WEATHER_CACHE);
        return Observable.just(weather);
    });
}

然后我們將他們連接起來:

private void load() {
    Observable.concat(fetchDataByNetWork(), fetchDataByCache())
        .first(weather -> weather != null)
        .doOnError(throwable -> {
            mErroImageView.setVisibility(View.VISIBLE);
            mRecyclerView.setVisibility(View.GONE);
        })
        .doOnNext(weather -> {
            mErroImageView.setVisibility(View.GONE);
            mRecyclerView.setVisibility(View.VISIBLE);
        })
        .doOnTerminate(() -> {
            mRefreshLayout.setRefreshing(false);
            mProgressBar.setVisibility(View.GONE);
        })
        .subscribe(observer);
}

concat + first 連接和過濾的操作實現(xiàn)了,網(wǎng)絡+緩存的邏輯。

剛剛為什么說要在網(wǎng)絡代碼那里使用 onErrorReturn 呢?

如果不寫,網(wǎng)絡發(fā)生異常的話,整個流就會直接走 onError ,不會執(zhí)行到讀取緩存的流。

結(jié)語

Rx 的各種操作符的不同組合就可以實現(xiàn)不同的效果。本身 Rx 封裝已經(jīng)足夠好了,我們加工的時候一定要想到是否破壞了他本身的優(yōu)雅。

因為 Rx 是一種數(shù)據(jù)流鏈式結(jié)構(gòu)的編程思想,我們在封裝時應該不能打斷其鏈式結(jié)構(gòu)。

歡迎互相討論和探討 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容