RxJava開發精要5 – Observables變換

在上一章中,咱們探索了RxJava通用過濾方法。咱們學習瞭如何使用filter()方法過濾咱們不須要的值,如何使用take()獲得發射元素的子集,如何使用distinct()函數來去除重複的。咱們學習瞭如何使用timeout()sample(),以及debounce()來利用時間。git

這一章中,咱們將學習如何變換可觀測序列來建立一個更好知足咱們需求的序列。github

*map家族

RxJava提供了幾個mapping函數:map(),flatMap(),concatMap(),flatMapIterable()以及switchMap().全部這些函數都做用於一個可觀測序列,而後變換它發射的值,最後用一種新的形式返回它們。讓咱們用「真實世界」合適的例子一個個的學習下。緩存

Map

RxJava的map函數接收一個指定的Func對象而後將它應用到每個由Observable發射的值上。下圖展現瞭如何將一個乘法函數應用到每一個發出的值上以此建立一個新的Observable來發射轉換的數據。app

考慮咱們已安裝的應用列表。咱們怎麼纔可以顯示一樣的列表,可是全部的名字都是小寫。eclipse

咱們的loadList()函數能夠改爲這樣:async

 

 

正如你看到的,像往常同樣建立咱們發射的Observable,咱們加一個map調用,咱們能夠建立一個簡單的函數來更新AppInfo對象並提供一個名字小寫的新版本給觀察者。ide

FlatMap

在複雜的場景中,咱們有一個這樣的Observable:它發射一個數據序列,這些數據自己也能夠發射Observable。RxJava的flatMap()函數提供一種鋪平序列的方式,而後合併這些Observables發射的數據,最後將合併後的結果做爲最終的Observable。函數

當咱們在處理可能有大量的Observables時,重要是記住任何一個Observables發生錯誤的狀況,flatMap()函數將會觸發它本身的onError()函數並放棄整個鏈。學習

重要的一點是關於合併部分:它容許交叉。正如上圖所示,這意味着flatMap()函數在最後的Observable中不可以保證源Observables確切的發射順序。url

ConcatMap

RxJava的concatMap()函數解決了flatMap()的交叉問題,提供了一種可以把發射的值連續在一塊兒的鋪平函數,而不是合併它們,以下圖所示:

FlatMapIterable

做爲*map家族的一員,flatMapInterable()flatMap()很像。僅有的本質不一樣是它將源數據兩兩結成對,而後生成Iterable而不是原始數據和生成的Observables。

SwitchMap

以下圖所示,switchMap()flatMap()很像,除了一點:當原始Observable發射一個新的數據(Observable)時,它將取消訂閱並中止監視以前那個數據的Observable產生的Observable,並開始監視當前這一個。

Scan

RxJava的scan()函數能夠看作是一個累加器函數。scan()函數對原始Observable發射的每一項數據都應用一個函數,它將函數的結果填充回可觀測序列,等待和下一次發射的數據一塊兒使用。

做爲一個通用的例子,給出一個累加器:

 

 

咱們獲得的結果是:

 

 

咱們也能夠建立一個新版本的loadList()函數用來比較每一個安裝應用的名字從而建立一個名字長度遞增的列表。

 

 

結果以下:

有一個scan()函數的變體,它用初始值做爲第一個發射的值,方法特徵就像:scan(R,Func2),就像下圖中的例子這樣:

GroupBy

拿第一個例子開始,咱們安裝的應用程序列表按照字母表的順序排序。然而,若是如今咱們想按照最近更新日期來排序咱們的App時該怎麼辦?RxJava提供了一個有用的函數從列表中按照指定的規則:groupBy()來分組元素。下圖中的例子展現了groupBy()如何將發射的值根據他們的形狀來進行分組。

這個函數將源Observable變換成一個發射Observables的新的Observable。它們中的每個新的Observable都發射一組指定的數據。

爲了建立一個分組了的已安裝應用列表,咱們在loadList()函數中引入了一個新的元素:

 

 

如今咱們建立了一個新的Observable,groupedItems,將會發射一個帶有GroupedObservable的序列。GroupedObservable是一個特殊的Observable,它源自一個分組的key。在這個例子中,key就是String,表明的意思是Month/Year格式化的最近更新日期。

這一點,咱們已經建立了幾個發射AppInfo數據的Observable,用來填充咱們的列表。咱們想保留字母排序和分組排序。咱們將建立一個新的Observable將全部的聯繫起來,像一般同樣而後訂閱它:

 

 

咱們的loadList()函數完成了,結果是:

Buffer

RxJava中的buffer()函數將源Observable變換一個新的Observable,這個新的Observable每次發射一組列表值而不是一個一個發射。

上圖中展現了buffer()如何將count做爲一個參數來指定有多少數據項被包在發射的列表中。實際上,buffer()函數有幾種變體。其中有一個時容許你指定一個skip值:此後每當收到skip項數據,用count項數據就填充緩存。以下圖所示:

buffer()帶一個timespan的參數,會建立一個每隔timespan時間段就會發射一個列表的Observable。

Window

RxJava的window()函數和buffer()很像,可是它發射的時Observable而不是列表。下圖展現了window()如何緩存3個數據項並把它們做爲一個新的Observable發射出去。

這些Observables中的每個都發射原始Observable數據的一個子集,數量由count指定,最後發射一個onCompleted()結束。正如buffer()同樣,window()也有一個skip變體,以下圖所示:

Cast

RxJava的cast()函數是本章中最後一個操做符。它是map()操做符的特殊版本。它將源Observable中的每一項數據都轉換爲新的類型,把它變成了不一樣的Class

總結

這一章中,咱們學習了RxJava時如何控制和轉換可觀測序列。用咱們如今所學的知識,咱們能夠建立、過濾、轉換咱們所想要的任何種類的可觀測序列。

下一章,咱們將學習如何組合Observable,合併它們,鏈接它們,再或者打包它們。

相關文章
相關標籤/搜索