1. 程式人生 > >RxJava變換操作符:.concatMap( )與.flatMap( )的比較(即有序對無序)

RxJava變換操作符:.concatMap( )與.flatMap( )的比較(即有序對無序)

原文連結: RxJava Observable tranformation: concatMap() vs flatMap() 原文作者: Fernando Cejas譯文出自: 小鄧子的簡書譯者: 小鄧子校對者: hi大頭鬼hi狀態: 完成
是時候迴歸寫作了。(譯者注:原作者吧啦吧啦嘮家常,這裡就不做翻譯了,但是,有兩個重要的連結,點我再點我Observable 轉換當你有一個需要訂閱的Observable,並且希望轉換結果的時候(切記,響應式程式設計中一切皆流)。即將涉及到observable轉換的時候,從佇列中取出將要消費的事件,不可能一直是我們需要的格式或者形狀,可能每個值都需要擴充套件成更豐富的物件或者化作更多的值。為了達到目的,我們可以為每一個observable

的返回值使用一個這樣的方法函式,使用它可以將所有已傳送的事件轉換成各種Observable,並最終合併結果。不要擔心,不能馬上理解這種概念(關於響應式,我也思考了一段時間),讓我們來看一個小栗子吧。問題我需要從資料庫檢索出一組數值,然後每個數值都要呼叫這樣的一個方法,它不僅支援非同步轉換,還能維持之前的輸出順序。最後,將他們轉換成UI展示所需的列表。然而蛋疼的是,結果並不是我想要的,因為:我使用了一個不能維持元素順序的操作符Observable.flatMap()簡單示例讓我用一個簡單示例演示上面提到的事情。我們有一個能夠傳送整型(物件)事件的Observable,並且能夠計算每個值的平方和。public
class DataManager {private final List<Integer> numbers; private final Executor jobExecutor; publicDataManager() { this.numbers = new ArrayList<>(Arrays.asList(2,3, 4, 5, 6, 7,8, 9, 10)); jobExecutor = JobExecutor.getInstance(); } public Observable<Integer> getNumbers() { return
Observable.from(numbers); }public List<Integer> getNumbersSync() { return this.numbers; } public Observable<Integer> squareOf(int number) {return Observable.just(number * number).subscribeOn(Schedulers.from(this.jobExecutor)); }}
這個DataManager類有一個方法:能夠生成一個可以傳送2到10的數字事件的Observable。因此可以用這個方法計算每個值的平方和。privatefinal Func1<Integer, Observable<Integer>> SQUARE_OF_NUMBER =new Func1<Integer, Observable<Integer>>() {@Override public Observable<Integer>call(Integer number){ return dataManager.squareOf(number); }};把每個Integer作為一個實體,生成一個Observable<Integer>,合併,然後傳送結果。如你所看到的,dataManager.squareOf()是一個非同步方法(為達到演示目的),看起來是這樣的:public Observable<Integer> squareOf(int number){return Observable.just(number * number).subscribeOn(Schedulers.from(this.jobExecutor));}雖然這也能執行,但並不是預期結果(至少不是我想要的),因為元素的順序被打亂了。

logcat 輸出flatMap()與concatMap()的比較這兩個方法似乎相差無幾,但有一點不同:用操作符合並最終結果的時候。這裡有一些官網的東西:

flatMap()操作符使用你提供的原本會被原始Observable傳送的事件,來建立一個新的Observable。而且這個操作符,返回的是一個自身傳送事件併合並結果的Observable。可以用於任何由原始Observable傳送出的事件,傳送合併後的結果。記住,flatMap()可能交錯的傳送事件,最終結果的順序可能並是不原始Observable傳送時的順序。為了防止交錯的發生,可以使用與之類似的concatMap()操作符。
如你所見,這兩個方法非常的相似,只在形成輸出的時候存在微小的區別(在map()操作符執行完畢後)(譯者注:通過翻看原始碼,會發現無論flatMap()還是concatMap()都包裹了一層map()操作符)。flatMap()使用merge()操作符,而concatMap()使用concat()操作符,這就意味著後者(譯者注:這裡的後者指concatMap())遵循元素的順序,所以,請留意是否需要保持元素次序:)。(譯者注:關於:)這個表情,請將螢幕旋轉90°)Merge operator將多個Observable合併成一個。
Concat operator按順序依次連線兩個或更多的Observable
Problem solvedconcatMap()的救贖。把flatMap()替換成concatMap(),問題迎刃而解。你可能會問:為什麼不首先閱讀文件(歸功於RxJava的貢獻者),有時候我們真的很懶,不到萬不得已絕不會去查閱文件。這張圖是經過測試後的最終結果(可以在最下面找到示例程式碼):
參考文獻希望我的片面之詞能夠對你有所幫助,一如既往的將示例程式碼和其他一些值得讀的資料羅列在這裡。原始碼: https://github.com/android10/Android-ReactiveProgrammingFunctional Reactive Programming on Android With RxJavaGrokking RxJavaTop 7 Tips for RxJava on AndroidMastering ObservablesReact Conference London