【譯】RxJava變換操作符:.concatMap( )與.flatMap( )的比較

是時(shí)候回歸寫作了。(譯者注:原作者吧啦吧啦嘮家常,這里就不做翻譯了,但是,有兩個(gè)重要的鏈接,點(diǎn)我再點(diǎn)我

Observable 轉(zhuǎn)換

當(dāng)你有一個(gè)需要訂閱的Observable,并且希望轉(zhuǎn)換結(jié)果的時(shí)候(切記,響應(yīng)式編程中一切皆流)。即將涉及到observable轉(zhuǎn)換的時(shí)候,從隊(duì)列中取出將要消費(fèi)的事件,不可能一直是我們需要的格式或者形狀,可能每個(gè)值都需要擴(kuò)展成更豐富的對象或者化作更多的值。為了達(dá)到目的,我們可以為每一個(gè)observable的返回值使用一個(gè)這樣的方法函數(shù),使用它可以將所有已發(fā)送的事件轉(zhuǎn)換成各種Observable,并最終合并結(jié)果。不要擔(dān)心,不能馬上理解這種概念(關(guān)于響應(yīng)式,我也思考了一段時(shí)間),讓我們來看一個(gè)小栗子吧。

問題

我需要從數(shù)據(jù)庫檢索出一組數(shù)值,然后每個(gè)數(shù)值都要調(diào)用這樣的一個(gè)方法,它不僅支持異步轉(zhuǎn)換,還能維持之前的輸出順序。最后,將他們轉(zhuǎn)換成UI展示所需的列表。然而蛋疼的是,結(jié)果并不是我想要的,因?yàn)椋何沂褂昧艘粋€(gè)不能維持元素順序的操作符 Observable.flatMap()

簡單示例

讓我用一個(gè)簡單示例演示上面提到的事情。我們有一個(gè)能夠發(fā)送整型(對象)事件的Observable,并且能夠計(jì)算每個(gè)值的平方和。

 public class DataManager {
 private final List<Integer> numbers;
 private final Executor jobExecutor;

 public DataManager() {
   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));
 }
}

這個(gè)DataManager類有一個(gè)方法:能夠生成一個(gè)可以發(fā)送2到10的數(shù)字事件的Observable。因此可以用這個(gè)方法計(jì)算每個(gè)值的平方和。

private final Func1<Integer, Observable<Integer>> SQUARE_OF_NUMBER =
new Func1<Integer, Observable<Integer>>() {
  @Override public Observable<Integer> call(Integer number) {
    return dataManager.squareOf(number);
  }
};

把每個(gè)Integer作為一個(gè)實(shí)體,生成一個(gè)Observable<Integer>,合并,然后發(fā)送結(jié)果。如你所看到的,dataManager.squareOf()是一個(gè)異步方法(為達(dá)到演示目的),看起來是這樣的:

public Observable<Integer> squareOf(int number) {
return Observable.just(number * number).subscribeOn(Schedulers.from(this.jobExecutor));
}

雖然這也能運(yùn)行,但并不是預(yù)期結(jié)果(至少不是我想要的),因?yàn)樵氐捻樞虮淮騺y了。


logcat 輸出

flatMap()與concatMap()的比較

這兩個(gè)方法似乎相差無幾,但有一點(diǎn)不同:用操作符合并最終結(jié)果的時(shí)候。這里有一些官網(wǎng)的東西:


flatMap()操作符使用你提供的原本會(huì)被原始Observable發(fā)送的事件,來創(chuàng)建一個(gè)新的Observable。而且這個(gè)操作符,返回的是一個(gè)自身發(fā)送事件并合并結(jié)果的Observable。可以用于任何由原始Observable發(fā)送出的事件,發(fā)送合并后的結(jié)果。記住,flatMap()可能交錯(cuò)的發(fā)送事件,最終結(jié)果的順序可能并是不原始Observable發(fā)送時(shí)的順序。為了防止交錯(cuò)的發(fā)生,可以使用與之類似的concatMap()操作符。

如你所見,這兩個(gè)方法非常的相似,只在形成輸出的時(shí)候存在微小的區(qū)別(在map()操作符執(zhí)行完畢后)(譯者注:通過翻看源碼,會(huì)發(fā)現(xiàn)無論flatMap()還是concatMap()都包裹了一層map()操作符)。flatMap()使用merge()操作符,而concatMap()使用concat()操作符,這就意味著后者(譯者注:這里的后者指concatMap())遵循元素的順序,所以,請留意是否需要保持元素次序:)。(譯者注:關(guān)于:)這個(gè)表情,請將屏幕旋轉(zhuǎn)90°)

Merge operator

將多個(gè)Observable合并成一個(gè)。

Concat operator

按順序依次連接兩個(gè)或更多的Observable

Problem solved

concatMap()的救贖。把flatMap()替換成concatMap(),問題迎刃而解。你可能會(huì)問:為什么不首先閱讀文檔(歸功于RxJava的貢獻(xiàn)者),有時(shí)候我們真的很懶,不到萬不得已絕不會(huì)去查閱文檔。這張圖是經(jīng)過測試后的最終結(jié)果(可以在最下面找到示例代碼):

參考文獻(xiàn)

希望我的片面之詞能夠?qū)δ阌兴鶐椭蝗缂韧膶⑹纠a和其他一些值得讀的資料羅列在這里。

  1. 源碼: https://github.com/android10/Android-ReactiveProgramming
  2. Functional Reactive Programming on Android With RxJava
  3. Grokking RxJava
  4. Top 7 Tips for RxJava on Android
  5. Mastering Observables
  6. React Conference London

如果有更好的辦法或者其他問題,歡迎任何形式的反饋(譯者注:當(dāng)然,小鄧子也歡迎任何形式的反饋)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評(píng)論 3 426
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,315評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評(píng)論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,882評(píng)論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,189評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,388評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,613評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評(píng)論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,112評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,334評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容