程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java的RxJava庫操作符的用法及實例講授

Java的RxJava庫操作符的用法及實例講授

編輯:關於JAVA

Java的RxJava庫操作符的用法及實例講授。本站提示廣大學習愛好者:(Java的RxJava庫操作符的用法及實例講授)文章只能為提供參考,不一定能成為您想要的結果。以下是Java的RxJava庫操作符的用法及實例講授正文


操作符就是為懂得決對Observable對象的變換的成績,操作符用於在Observable和終究的Subscriber之間修正Observable收回的事宜。RxJava供給了許多很有效的操作符。
好比map操作符,就是用來把把一個事宜轉換為另外一個事宜的。

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可以簡化為

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

是否是很酷?map()操作符就是用於變換Observable對象的,map操作符前往一個Observable對象,如許便可以完成鏈式挪用,在一個Observable對象上屢次應用map操作符,終究將最簡練的數據傳遞給Subscriber對象。


map操作符進階
map操作符更風趣的一點是它不用前往Observable對象前往的類型,你可使用map操作符前往一個收回新的數據類型的observable對象。
好比下面的例子中,subscriber其實不關懷前往的字符串,而是想要字符串的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,固然應用lambda可以進一步簡化代碼:
 

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

後面說過,Subscriber做的工作越少越好,我們再增長一個map操作符
 

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

不服?
是否是認為我們的例子太簡略,缺乏以壓服你?你須要明確上面的兩點:
1.Observable和Subscriber可以做任何工作
Observable可所以一個數據庫查詢,Subscriber用來顯示查詢成果;Observable可所以屏幕上的點擊事宜,Subscriber用來呼應點擊事宜;Observable可所以一個收集要求,Subscriber用來顯示要求成果。
2.Observable和Subscriber是自力於中央的變換進程的。
在Observable和Subscriber中央可以增減任何數目的map。全部體系是高度可組合的,操作數據是一個很簡略的進程。

實例
1.預備任務
假定我有如許一個辦法:
這個辦法依據輸出的字符串前往一個網站的url列表(啊哈,搜刮引擎)
 

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

如今我願望構建一個硬朗體系,它可以查詢字符串而且顯示成果。依據上一篇blog的內容,我們能夠會寫出上面的代碼:
 

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

這類代碼固然是不克不及容忍的,由於下面的代碼使我們損失了變更數據流的才能。一旦我們想要更改每個URL,只能在Subscriber中來做。我們居然沒有應用如斯酷的map()操作符!!!

固然,我可使用map操作符,map的輸出是urls列表,處置的時刻照樣要for each遍歷,一樣很蛋疼。

萬幸,還有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輪回,然則代碼仍然看起來很亂。多個嵌套的subscription不只看起來很丑,難以修正,更嚴重的是它會損壞某些我們如今還沒有講到的RxJava的特征。

2.改良
救星來了,他就是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)); 

這裡我貼出了全部的函數代碼,以便利你懂得產生了甚麼,應用lambda可以年夜年夜簡化代碼長度:

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

flatMap()是否是看起來很奇異?為何它要前往別的一個Observable呢?懂得flatMap的症結點在於,flatMap輸入的新的Observable恰是我們在Subscriber想要吸收的。如今Subscriber不再收到List<String>,而是收到一些列單個的字符串,就像Observable.from()的輸入一樣。

這部門也是我現在學RxJava的時刻最難懂得的部門,一旦我忽然融會了,RxJava的許多疑問也就一並處理了。

3.還可以更好
flatMap()其實不克不及更贊了,它可以前往任何它想前往的Observable對象。
好比上面的辦法: 

// 前往網站的題目,假如404了就前往null 
Observable<String> getTitle(String URL); 


接著後面的例子,如今我不想打印URL了,而是要打印收到的每一個網站的題目。成績來了,我的辦法每次只能傳入一個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)); 

4.應用lambda:

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

是否是感到很弗成思議?我居然能將多個自力的前往Observable對象的辦法組合在一路!帥呆了!
不止這些,我還將兩個API的挪用組合到一個鏈式挪用中了。我們可以將隨意率性多個API挪用鏈接起來。年夜家應當都應當曉得同步一切的API挪用,然後將一切API挪用的回調成果組分解須要展現的數據是一件何等蛋疼的工作。這裡我們勝利的防止了callback hell(多層嵌套的回調,招致代碼難以浏覽保護)。如今一切的邏輯都包裝成了這類簡略的呼應式挪用。

5.豐碩的操作符
今朝為止,我們曾經接觸了兩個操作符,RxJava中還有更多的操作符,那末我們若何應用其他的操作符來改良我們的代碼呢?
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個成果:
 

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()輸入最多指定命量的成果。

假如我們想在打印之前,把每一個題目保留到磁盤: 

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()許可我們在每次輸入一個元素之前做一些額定的工作,好比這裡的保留題目。

看到這裡操作數據流是何等簡略了麼。你可以添加隨意率性多的操作,而且不會弄亂你的代碼。

RxJava包括了年夜量的操作符。操作符的數目是有點嚇人,然則很值得你去挨個看一下,如許你可以曉得有哪些操作符可使用。弄懂這些操作符能夠會花一些時光,然則一旦弄懂了,你就完整控制了RxJava的威力。

你乃至可以編寫自界說的操作符!這篇blog不盤算將自界說操作符,假如你想的話,清自行Google吧。

感到若何?
好吧,你是一個疑惑主義者,而且還很難被壓服,那為何你要關懷這些操作符呢?

由於操作符可讓你對數據流做任何操作。

將一系列的操作符鏈接起來便可以完成龐雜的邏輯。代碼被分化成一系列可以組合的片斷。這就是呼應式函數編程的魅力。用的越多,就會越多的轉變你的編程思想。

別的,RxJava也使我們處置數據的方法變得更簡略。在最初一個例子裡,我們挪用了兩個API,對API前往的數據停止了處置,然後保留到磁盤。然則我們的Subscriber其實不曉得這些,它只是以為本身在吸收一個Observable<String>對象。優越的封裝性也帶來了編碼的方便!


在第三部門中,我將引見RxJava的別的一些很酷的特征,好比毛病處置和並發,這些特征其實不會直接用來處置數據。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved