RxJava變換操作符:.concatMap( )與.flatMap( )的比較(即有序對無序)
阿新 • • 發佈:2019-02-15
原文連結:
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 solved
concatMap()
的救贖。把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