欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的RxJava庫(kù)操作符的用法及實(shí)例講解

 更新時(shí)間:2016年06月18日 11:59:38   作者:hi大頭鬼hi  
RxJava由于提供異步和基于事件的支持在Android開(kāi)發(fā)者中獲得了不少人氣,這里我們就來(lái)看一下Java的RxJava庫(kù)操作符的用法及實(shí)例講解,需要的朋友可以參考下

操作符就是為了解決對(duì)Observable對(duì)象的變換的問(wèn)題,操作符用于在Observable和最終的Subscriber之間修改Observable發(fā)出的事件。RxJava提供了很多很有用的操作符。
比如map操作符,就是用來(lái)把把一個(gè)事件轉(zhuǎn)換為另一個(gè)事件的。

Observable.just("Hello, world!") 
 .map(new Func1<String, String>() { 
   @Override 
   public String call(String s) { 
     return s + " -Dan"; 
   } 
 }) 
 .subscribe(s -> System.out.println(s)); 

使用lambda可以簡(jiǎn)化為

 
Observable.just("Hello, world!") 
  .map(s -> s + " -Dan") 
  .subscribe(s -> System.out.println(s)); 

是不是很酷?map()操作符就是用于變換Observable對(duì)象的,map操作符返回一個(gè)Observable對(duì)象,這樣就可以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,在一個(gè)Observable對(duì)象上多次使用map操作符,最終將最簡(jiǎn)潔的數(shù)據(jù)傳遞給Subscriber對(duì)象。


map操作符進(jìn)階
map操作符更有趣的一點(diǎn)是它不必返回Observable對(duì)象返回的類(lèi)型,你可以使用map操作符返回一個(gè)發(fā)出新的數(shù)據(jù)類(lèi)型的observable對(duì)象。
比如上面的例子中,subscriber并不關(guān)心返回的字符串,而是想要字符串的hash值
 

Observable.just("Hello, world!") 
  .map(new Func1<String, Integer>() { 
    @Override 
    public Integer call(String s) { 
      return s.hashCode(); 
    } 
  }) 
  .subscribe(i -> System.out.println(Integer.toString(i))); 

很有趣吧?我們初始的Observable返回的是字符串,最終的Subscriber收到的卻是Integer,當(dāng)然使用lambda可以進(jìn)一步簡(jiǎn)化代碼:
 

Observable.just("Hello, world!") 
  .map(s -> s.hashCode()) 
  .subscribe(i -> System.out.println(Integer.toString(i))); 

前面說(shuō)過(guò),Subscriber做的事情越少越好,我們?cè)僭黾右粋€(gè)map操作符
 

Observable.just("Hello, world!") 
  .map(s -> s.hashCode()) 
  .map(i -> Integer.toString(i)) 
  .subscribe(s -> System.out.println(s)); 

不服?
是不是覺(jué)得我們的例子太簡(jiǎn)單,不足以說(shuō)服你?你需要明白下面的兩點(diǎn):
1.Observable和Subscriber可以做任何事情
Observable可以是一個(gè)數(shù)據(jù)庫(kù)查詢(xún),Subscriber用來(lái)顯示查詢(xún)結(jié)果;Observable可以是屏幕上的點(diǎn)擊事件,Subscriber用來(lái)響應(yīng)點(diǎn)擊事件;Observable可以是一個(gè)網(wǎng)絡(luò)請(qǐng)求,Subscriber用來(lái)顯示請(qǐng)求結(jié)果。
2.Observable和Subscriber是獨(dú)立于中間的變換過(guò)程的。
在Observable和Subscriber中間可以增減任何數(shù)量的map。整個(gè)系統(tǒng)是高度可組合的,操作數(shù)據(jù)是一個(gè)很簡(jiǎn)單的過(guò)程。

實(shí)例
1.準(zhǔn)備工作
假設(shè)我有這樣一個(gè)方法:
這個(gè)方法根據(jù)輸入的字符串返回一個(gè)網(wǎng)站的url列表(啊哈,搜索引擎)
 

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

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

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

這種代碼當(dāng)然是不能容忍的,因?yàn)樯厦娴拇a使我們喪失了變化數(shù)據(jù)流的能力。一旦我們想要更改每一個(gè)URL,只能在Subscriber中來(lái)做。我們竟然沒(méi)有使用如此酷的map()操作符?。。?/p>

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

萬(wàn)幸,還有Observable.from()方法,它接收一個(gè)集合作為輸入,然后每次輸出一個(gè)元素給subscriber:
 

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

我們來(lái)把這個(gè)方法使用到剛才的場(chǎng)景: 

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


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

2.改進(jìn)
救星來(lái)了,他就是flatMap()。
Observable.flatMap()接收一個(gè)Observable的輸出作為輸入,同時(shí)輸出另外一個(gè)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)); 

這里我貼出了整個(gè)的函數(shù)代碼,以方便你了解發(fā)生了什么,使用lambda可以大大簡(jiǎn)化代碼長(zhǎng)度:

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

flatMap()是不是看起來(lái)很奇怪?為什么它要返回另外一個(gè)Observable呢?理解flatMap的關(guān)鍵點(diǎn)在于,flatMap輸出的新的Observable正是我們?cè)赟ubscriber想要接收的?,F(xiàn)在Subscriber不再收到List<String>,而是收到一些列單個(gè)的字符串,就像Observable.from()的輸出一樣。

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

3.還可以更好
flatMap()實(shí)在不能更贊了,它可以返回任何它想返回的Observable對(duì)象。
比如下面的方法: 

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


接著前面的例子,現(xiàn)在我不想打印URL了,而是要打印收到的每個(gè)網(wǎng)站的標(biāo)題。問(wèn)題來(lái)了,我的方法每次只能傳入一個(gè)URL,并且返回值不是一個(gè)String,而是一個(gè)輸出String的Observabl對(duì)象。使用flatMap()可以簡(jiǎn)單的解決這個(gè)問(wèn)題。 

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)); 

4.使用lambda:

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

是不是感覺(jué)很不可思議?我竟然能將多個(gè)獨(dú)立的返回Observable對(duì)象的方法組合在一起!帥呆了!
不止這些,我還將兩個(gè)API的調(diào)用組合到一個(gè)鏈?zhǔn)秸{(diào)用中了。我們可以將任意多個(gè)API調(diào)用鏈接起來(lái)。大家應(yīng)該都應(yīng)該知道同步所有的API調(diào)用,然后將所有API調(diào)用的回調(diào)結(jié)果組合成需要展示的數(shù)據(jù)是一件多么蛋疼的事情。這里我們成功的避免了callback hell(多層嵌套的回調(diào),導(dǎo)致代碼難以閱讀維護(hù))。現(xiàn)在所有的邏輯都包裝成了這種簡(jiǎn)單的響應(yīng)式調(diào)用。

5.豐富的操作符
目前為止,我們已經(jīng)接觸了兩個(gè)操作符,RxJava中還有更多的操作符,那么我們?nèi)绾问褂闷渌牟僮鞣麃?lái)改進(jìn)我們的代碼呢?
getTitle()返回null如果url不存在。我們不想輸出"null",那么我們可以從返回的title列表中過(guò)濾掉null值!

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

filter()輸出和輸入相同的元素,并且會(huì)過(guò)濾掉那些不滿(mǎn)足檢查條件的。

如果我們只想要最多5個(gè)結(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é)果。

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

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()允許我們?cè)诿看屋敵鲆粋€(gè)元素之前做一些額外的事情,比如這里的保存標(biāo)題。

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

RxJava包含了大量的操作符。操作符的數(shù)量是有點(diǎn)嚇人,但是很值得你去挨個(gè)看一下,這樣你可以知道有哪些操作符可以使用。弄懂這些操作符可能會(huì)花一些時(shí)間,但是一旦弄懂了,你就完全掌握了RxJava的威力。

你甚至可以編寫(xiě)自定義的操作符!這篇blog不打算將自定義操作符,如果你想的話(huà),清自行Google吧。

感覺(jué)如何?
好吧,你是一個(gè)懷疑主義者,并且還很難被說(shuō)服,那為什么你要關(guān)心這些操作符呢?

因?yàn)椴僮鞣梢宰屇銓?duì)數(shù)據(jù)流做任何操作。

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

另外,RxJava也使我們處理數(shù)據(jù)的方式變得更簡(jiǎn)單。在最后一個(gè)例子里,我們調(diào)用了兩個(gè)API,對(duì)API返回的數(shù)據(jù)進(jìn)行了處理,然后保存到磁盤(pán)。但是我們的Subscriber并不知道這些,它只是認(rèn)為自己在接收一個(gè)Observable<String>對(duì)象。良好的封裝性也帶來(lái)了編碼的便利!


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

相關(guān)文章

  • 關(guān)于Java中重定向傳參與取值

    關(guān)于Java中重定向傳參與取值

    這篇文章主要介紹了Java中重定向傳參與取值問(wèn)題,重定向不僅可以重定向到當(dāng)前應(yīng)用程序中的其他資源,還可以重定向到同一個(gè)站點(diǎn)上的其他應(yīng)用程序中的資源,甚至是使用絕對(duì)URL重定向到其他站點(diǎn)的資源,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • 淺談slf4j中的橋接器是如何運(yùn)作的

    淺談slf4j中的橋接器是如何運(yùn)作的

    這篇文章主要介紹了slf4j中的橋接器是如何運(yùn)作的,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • PowerJob的AbstractScriptProcessor實(shí)現(xiàn)類(lèi)工作流程源碼解讀

    PowerJob的AbstractScriptProcessor實(shí)現(xiàn)類(lèi)工作流程源碼解讀

    這篇文章主要為大家介紹了PowerJob的AbstractScriptProcessor源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類(lèi)型)

    Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類(lèi)型)

    這篇文章主要介紹了Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類(lèi)型),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Java查看和修改線(xiàn)程優(yōu)先級(jí)操作詳解

    Java查看和修改線(xiàn)程優(yōu)先級(jí)操作詳解

    JAVA中每個(gè)線(xiàn)程都有優(yōu)化級(jí)屬性,默認(rèn)情況下,新建的線(xiàn)程和創(chuàng)建該線(xiàn)程的線(xiàn)程優(yōu)先級(jí)是一樣的。本文將為大家詳解Java查看和修改線(xiàn)程優(yōu)先級(jí)操作的方法,需要的可以參考一下
    2022-08-08
  • Java虛擬機(jī)JVM性能優(yōu)化(三):垃圾收集詳解

    Java虛擬機(jī)JVM性能優(yōu)化(三):垃圾收集詳解

    這篇文章主要介紹了Java虛擬機(jī)JVM性能優(yōu)化(三):垃圾收集詳解,本文講解了眾多的JVM垃圾收集器知識(shí)點(diǎn),需要的朋友可以參考下
    2014-09-09
  • 一文帶你解讀Java序列化和反序列化機(jī)制

    一文帶你解讀Java序列化和反序列化機(jī)制

    序列化是將對(duì)象轉(zhuǎn)換成二進(jìn)制字節(jié)流的過(guò)程;反序列化是從二進(jìn)制字節(jié)流中恢復(fù)對(duì)象的過(guò)程。本文將大家詳細(xì)講講二者的原理與實(shí)現(xiàn),希望對(duì)大家有所幫助
    2023-01-01
  • java如何實(shí)現(xiàn)圖片轉(zhuǎn)化為數(shù)據(jù)流

    java如何實(shí)現(xiàn)圖片轉(zhuǎn)化為數(shù)據(jù)流

    這篇文章主要介紹了java如何實(shí)現(xiàn)圖片轉(zhuǎn)化為數(shù)據(jù)流,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • java定時(shí)任務(wù)的實(shí)現(xiàn)方式

    java定時(shí)任務(wù)的實(shí)現(xiàn)方式

    這篇文章主要介紹了java定時(shí)任務(wù)的實(shí)現(xiàn)方式,在應(yīng)用里經(jīng)常都有用到在后臺(tái)跑定時(shí)任務(wù)的需求,如何進(jìn)行java定時(shí)任務(wù),本文為大家進(jìn)行講解,感興趣的小伙伴們可以參考一下
    2016-02-02
  • spring boot添加新模塊的方法教程

    spring boot添加新模塊的方法教程

    這篇文章主要給大家介紹了關(guān)于spring boot添加新模塊的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評(píng)論