理解RxJava:(二)Operator,Operator

第一部分,我講解了RxJava的基本結構,也介紹了map()操作。然而,我能理解你仍舊不會選擇使用Rxjava——你仍然還有很多東西沒有學到。但是這個情況將很快得到改變。Rxjava一大部分的能力是因為其中的operators。

讓我們通過一個例子來向你們介紹更多的operators。

初始

假設我有一個這樣的方法:

//返回一個基于文本查詢網站鏈接的列表
Observable<List<String>> query(String text); 

我想要構建一個搜索文本和顯示結果的強健系統?;谏掀恼挛覀儗W到的,以下是我們馬上想到的:

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

這個答案讓人非常不滿意,因為失去了轉換數據流的能力。如果我想要修改每個URL,只能在每個Subscriber里面修改。這就違背了使用map()操作的初衷。

我可以為ulrs->urls創建一個map(),但是每個map()的內部都有一個for-each循環。哎喲。

一線希望

有一個方法,Observable.from(),輸入一些items,然后每次發出一個:

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循環,但是代碼顯得很混亂?,F在變成了多個嵌套的subscriptions了。除了代碼丑陋以及難以修改外,也違背了RxJava的一些原則。

更好的方法

屏住你的呼吸,因為你見到了你的救世主: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?核心概念是新的Observable返回的正是Subscriber所觀察的。它不接收List<String>——它接收Observable.from()返回的一系列的單獨的Strings。

此外

我強調這個觀點幾遍都不足夠:flatMap()能返回任意想要的Observable

假設我又有一個這樣的方法:

// 返回網站的標題,若是404則返回null
Observable<String> getTitle(String URL);

原本是打印URL,現在我想要打印接收的每個網站的標題。但是有些問題:我的方法只對每次一個URL有效,而且它返回的不是String,它返回的是發出String的Observable。

有了flatMap(),解決這個問題很簡單。在把一系列的URL分開為單獨的items后,我可以在flatMap()方法中對于每個URL使用getTitle(),在它到達Subscriber前。

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調用組合在一條方法鏈上了。你們知道維持所有的API調用同步,必須在數據展示前將它們的回調寫在一起,是有多痛苦?我們不用再忍受嵌套回調了。所有的邏輯都包在簡短的響應式調用中了。

大量的Operators

到目前為止,我們僅僅學習了兩種operators。有很多還沒有學到。其他的operators能怎樣改善我們的代碼呢?

getTitle()在URL404的時候返回null。我們不想要輸出"null"。以下代碼顯示我們可以過濾掉null:

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

filter()方法發出和它們接收到的同樣的item,只在通過了boolean檢查的情況下。

現在我們只想要最多顯示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()最多發出指定數量的item(如果少于5個標題,它會提前停止)。

現在我們想要存儲每個標題到磁盤上:

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()讓我們可以在每次一個item被發出之前,添加額外的行為。

看操作數據流多么簡單。你可以繼續對數據添加操作而不會弄糟任何事情。

RxJava有非常多的Operators。這么多operators讓我們被嚇到,但是值得查閱一遍以知道哪個對我們有用。消化這些操作會花費點時間,但是我們能信手拈來的時候就能感受到Rxjava真正的強大。

以上都是官方提供的,我們甚至可以自定義operators!這超出了本文的討論范圍。但是只要你想你就能做到。

So What?

如果你是個懷疑論者。你會問為什么要關注這些operators?

關鍵點3 Operators讓你能對數據流做任何事

唯一的限制就是你自己。

你可以處理復雜的邏輯,從使用簡單的operators鏈開始。它將你的代碼打破為可重組的零碎東西。這就是函數響應式編程。你用的越多,就越能改變你編程的思維。

另外,想想我們的代碼一轉換消費起來變得多容易。最后的例子,我們調用了兩次API,操作數據,然后存儲。但是Subscriber并不知道這些。它想的僅僅是消費Observable<String>。封裝讓編程更簡單。

在第三部分,我們將繼續了解RxJava的特性。比如錯誤處理和并發,和操作數據沒有直接聯系。

本文翻譯自Grokking RxJava, Part 2: Operator Operator,著作權歸原作者danlew所有。譯文由JohnTsai翻譯。轉載請注明出處,并保留此段聲明。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,565評論 7 62
  • 前言我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占導zqq閱讀 9,193評論 6 151
  • 文章轉自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物線在正...
    xpengb閱讀 7,060評論 9 73
  • http://blog.csdn.net/yyh352091626/article/details/5330472...
    奈何心善閱讀 3,583評論 0 0
  • 小時候覺得表姐那么厲害,就以為張青姐姐以后有一天也會像她那樣考上好學校,她們都那樣努力,我就以為她們都會成為了不起...
    羅阿方閱讀 227評論 0 0