深入淺出RxJava(二:操作符)<譯>


文章轉(zhuǎn)載自:Hi大頭鬼_深入淺出RxJava(二:操作符)
個人感覺CSDN上看起來字體不是很舒服,所以轉(zhuǎn)載一下。

英文原文
第一篇blog中朗伶,我介紹了RxJava的一些基礎(chǔ)知識屯断,同時也介紹了map()操作符。當(dāng)然如果你并沒有意愿去使用RxJava我一點都不詫異瞒瘸,畢竟才接觸了這么點坷备。看完這篇blog情臭,我相信你肯定想立即在你的項目中使用RxJava了省撑,這篇blog將介紹許多RxJava中的操作符,RxJava的強大性就來自于它所定義的操作符俯在。

讓我們通過一個例子來向大家介紹更多的操作符(Operator)竟秫。

準(zhǔn)備工作

假設(shè)我有這樣一個方法:(這個方法根據(jù)輸入的字符串返回一個網(wǎng)站的url列表)

Observable<List<String>> query(String text);  

現(xiàn)在我希望構(gòu)建一個健壯系統(tǒng),它可以查詢字符串并且顯示結(jié)果跷乐。根據(jù)上一篇blog的內(nèi)容肥败,我們可能會寫出下面的代碼:

query("Hello, world!")  
    .subscribe(urls -> {  
        for (String url : urls) {  
            System.out.println(url);  
        }  
    });  

這種代碼當(dāng)然是不能容忍的,因為上面的代碼使我們喪失了變化數(shù)據(jù)流的能力愕提。一旦我們想要更改每一個URL馒稍,只能在Subscriber中來做。我們竟然沒有使用如此酷的map()操作符G城取E恕!

當(dāng)然如输,我可以使用map操作符鼓黔,map的輸入是urls列表,處理的時候還是要for each遍歷挨决,一樣很蛋疼请祖。

一線希望之 - Observable.from()

萬幸,還有Observable.from()方法脖祈,它接收一個集合作為輸入肆捕,然后每次輸出一個元素給subscriber:

Observable.from("url1", "url2", "url3")  
    .subscribe(url -> System.out.println(url));  

我們來把這個方法使用到剛才的場景:

query("Hello, world!")  
    .subscribe(urls -> {  
        Observable.from(urls)  
            .subscribe(url -> System.out.println(url));  
    }); 

雖然去掉了for each循環(huán),但是代碼依然看起來很亂盖高。多個嵌套的subscription不僅看起來很丑慎陵,難以修改眼虱,更嚴(yán)重的是它會破壞某些我們現(xiàn)在還沒有講到的RxJava的特性。

再次改進 - Observable.flatMap()

救星來了,他就是flatMap()席纽。
Observable.flatMap()接收一個Observable的輸出作為輸入捏悬,同時輸出另外一個Observable。直接看代碼:

query("Hello, world!")  
    .flatMap(new Func1<List<String>, Observable<String>>() {  
        @Override  
        public Observable<String> call(List<String> urls) {  
            return Observable.from(urls);  
        }  
    })  
    .subscribe(url -> System.out.println(url)); 

這里我貼出了整個的函數(shù)代碼润梯,以方便你了解發(fā)生了什么过牙,使用lambda可以大大簡化代碼長度:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .subscribe(url -> System.out.println(url));  

flatMap()是不是看起來很奇怪?為什么它要返回另外一個Observable呢纺铭?理解flatMap的關(guān)鍵點在于寇钉,flatMap輸出的新的Observable正是我們在Subscriber想要接收的。現(xiàn)在Subscriber不再收到List<String>舶赔,而是收到一些列單個的字符串扫倡,就像Observable.from()的輸出一樣。

這部分也是我當(dāng)初學(xué)RxJava的時候最難理解的部分竟纳,一旦我突然領(lǐng)悟了撵溃,RxJava的很多疑問也就一并解決了。

還可以更好

flatMap()實在不能更贊了锥累,它可以返回任何它想返回的Observable對象缘挑。
比如下面的方法:

// 返回網(wǎng)站的標(biāo)題,如果404了就返回null  
Observable<String> getTitle(String URL);  

接著前面的例子揩悄,現(xiàn)在我不想打印URL了卖哎,而是要打印收到的每個網(wǎng)站的標(biāo)題鬼悠。問題來了删性,我的方法每次只能傳入一個URL,并且返回值不是一個String焕窝,而是一個輸出String的Observabl對象蹬挺。使用flatMap()可以簡單的解決這個問題。

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(new Func1<String, Observable<String>>() {  
        @Override  
        public Observable<String> call(String url) {  
            return getTitle(url);  
        }  
    })  
    .subscribe(title -> System.out.println(title));  

使用lambda

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .subscribe(title -> System.out.println(title));  

是不是感覺很不可思議它掂?我竟然能將多個獨立的返回Observable對象的方法組合在一起巴帮!帥呆了!

不止這些虐秋,我還將兩個API的調(diào)用組合到一個鏈?zhǔn)秸{(diào)用中了榕茧。我們可以將任意多個API調(diào)用鏈接起來。大家應(yīng)該都應(yīng)該知道同步所有的API調(diào)用客给,然后將所有API調(diào)用的回調(diào)結(jié)果組合成需要展示的數(shù)據(jù)是一件多么蛋疼的事情用押。這里我們成功的避免了callback hell(多層嵌套的回調(diào),導(dǎo)致代碼難以閱讀維護)“薪#現(xiàn)在所有的邏輯都包裝成了這種簡單的響應(yīng)式調(diào)用蜻拨。

豐富的操作符

目前為止池充,我們已經(jīng)接觸了兩個操作符,RxJava中還有更多的操作符缎讼,那么我們?nèi)绾问褂闷渌牟僮鞣麃砀倪M我們的代碼呢收夸?
getTitle()返回null如果url不存在。我們不想輸出"null"血崭,那么我們可以從返回的title列表中過濾掉null值卧惜!

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .subscribe(title -> System.out.println(title));  

filter() 輸出和輸入相同的元素,并且會過濾掉那些不滿足檢查條件的夹纫。

如果我們只想要最多5個結(jié)果:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .take(5)  
    .subscribe(title -> System.out.println(title));  

take() 輸出最多指定數(shù)量的結(jié)果序苏。

如果我們想在打印之前,把每個標(biāo)題保存到磁盤:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .take(5)  
    .doOnNext(title -> saveTitle(title))  
    .subscribe(title -> System.out.println(title)); 

doOnNext() 允許我們在每次輸出一個元素之前做一些額外的事情捷凄,比如這里的保存標(biāo)題忱详。

看到這里操作數(shù)據(jù)流是多么簡單了么。你可以添加任意多的操作跺涤,并且不會搞亂你的代碼匈睁。

RxJava包含了大量的操作符。操作符的數(shù)量是有點嚇人桶错,但是很值得你去挨個看一下航唆,這樣你可以知道有哪些操作符可以使用。弄懂這些操作符可能會花一些時間院刁,但是一旦弄懂了糯钙,你就完全掌握了RxJava的威力。

你甚至可以編寫自定義的操作符退腥!這篇blog不打算將自定義操作符任岸,如果你想的話,請自行Google吧狡刘。

感覺如何享潜?

好吧,你是一個懷疑主義者嗅蔬,并且還很難被說服剑按,那為什么你要關(guān)心這些操作符呢?

因為操作符可以讓你對數(shù)據(jù)流做任何操作澜术。

將一系列的操作符鏈接起來就可以完成復(fù)雜的邏輯艺蝴。代碼被分解成一系列可以組合的片段。這就是響應(yīng)式函數(shù)編程的魅力鸟废。用的越多猜敢,就會越多的改變你的編程思維。

另外,RxJava也使我們處理數(shù)據(jù)的方式變得更簡單锣枝。在最后一個例子里厢拭,我們調(diào)用了兩個API,對API返回的數(shù)據(jù)進行了處理撇叁,然后保存到磁盤供鸠。但是我們的Subscriber并不知道這些,它只是認為自己在接收一個Observable<String>對象陨闹。良好的封裝性也帶來了編碼的便利楞捂!

在第三部分中,我將介紹RxJava的另外一些很酷的特性趋厉,比如錯誤處理和并發(fā)寨闹,這些特性并不會直接用來處理數(shù)據(jù)。

繼續(xù)下一篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末君账,一起剝皮案震驚了整個濱河市繁堡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乡数,老刑警劉巖椭蹄,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異净赴,居然都是意外死亡绳矩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門玖翅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翼馆,“玉大人,你說我怎么就攤上這事金度∮γ模” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵审姓,是天一觀的道長珍特。 經(jīng)常有香客問我祝峻,道長魔吐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任莱找,我火速辦了婚禮酬姆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奥溺。我一直安慰自己辞色,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布浮定。 她就那樣靜靜地躺著相满,像睡著了一般层亿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上立美,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天匿又,我揣著相機與錄音,去河邊找鬼建蹄。 笑死碌更,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洞慎。 我是一名探鬼主播痛单,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劲腿!你這毒婦竟也來了旭绒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤焦人,失蹤者是張志新(化名)和其女友劉穎快压,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垃瞧,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡蔫劣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了个从。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脉幢。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗦锐,靈堂內(nèi)的尸體忽然破棺而出嫌松,到底是詐尸還是另有隱情,我是刑警寧澤奕污,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布萎羔,位于F島的核電站,受9級特大地震影響碳默,放射性物質(zhì)發(fā)生泄漏贾陷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一嘱根、第九天 我趴在偏房一處隱蔽的房頂上張望髓废。 院中可真熱鬧,春花似錦该抒、人聲如沸慌洪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冈爹。三九已至涌攻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間频伤,已是汗流浹背癣漆。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剂买,地道東北人惠爽。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像瞬哼,于是被迫代替她去往敵國和親婚肆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

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