網(wǎng)絡(luò)請求
-
基本操作
RxJava 和 Retrofit 結(jié)合使用最基本的格式:用 subscribeOn() 和 observeOn() 來控制線程,并通過 subscribe() 來觸發(fā)網(wǎng)絡(luò)請求的開始莲祸。代碼大致形式:
api.getData().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
-
轉(zhuǎn)換Map
有些服務(wù)端的接口設(shè)計蹂安,會在返回的數(shù)據(jù)外層包裹一些額外信息,這些信息對于調(diào)試很有用锐帜,但本地顯示是用不到的田盈。使用 map() 可以把外層的格式剝掉,只留下本地會用到的核心格式缴阎。代碼大致形式:
api.getData().map(response -> response.data).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
當然允瞧,map() 也可以用于基于其他各種需求的格式轉(zhuǎn)換。
-
壓合zip
有的時候,app 中會需要同時訪問不同接口述暂,然后將結(jié)果糅合后轉(zhuǎn)為統(tǒng)一的格式后輸出(例如將第三方廣告 API 的廣告夾雜進自家平臺返回的數(shù)據(jù) List 中)痹升。這種并行的異步處理比較麻煩,不過用了 zip() 之后就會簡單得多畦韭。代碼大致形式:
Observable.zip(api.getData(),adApi.getAds(), zipFunc()).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
-
連續(xù)嵌套請求flatMap
出于安全性疼蛾、性能等方面的考慮,多數(shù)服務(wù)器會有一些接口需要傳入 token 才能正確返回結(jié)果艺配,而 token 是需要從另一個接口獲取的察郁,這就需要使用兩步連續(xù)的請求才能獲取數(shù)據(jù)(①token -> ②目標數(shù)據(jù))。使用 flatMap() 可以用較為清晰的代碼實現(xiàn)這種連續(xù)請求转唉,避免 Callback 嵌套的結(jié)構(gòu)皮钠。代碼大致形式:
api.getToken().flatMap(token -> api.getData(token)).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
-
錯誤重試retryWhen
有的 token 并非一次性的,而是可以多次使用赠法,直到它超時或被銷毀(多數(shù) token 都是這樣的)麦轰。這樣的 token 處理起來比較麻煩:需要把它保存起來,并且在發(fā)現(xiàn)它失效的時候要能夠自動重新獲取新的 token 并繼續(xù)訪問之前由于 token 失效而失敗的請求期虾。如果項目中有多處的接口請求都需要這樣的自動修復(fù)機制原朝,使用傳統(tǒng)的 Callback 形式需要寫出非常復(fù)雜的代碼。而使用 RxJava 镶苞,可以用 retryWhen() 來輕松地處理這樣的問題喳坠。
@Override
public Observable<?> apply(@NonNull Observable<? extends Throwable> attempts) throws Exception {
return attempts
.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
if (++retryCount <= maxRetries) {
// When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
Log.i(TAG, "get error, it will try after " + retryDelayMillis
+ " millisecond, retry count " + retryCount);
return Observable.timer(retryDelayMillis,
TimeUnit.MILLISECONDS);
}
// Max retries hit. Just pass the error along.
return Observable.error(throwable);
}
});
}