深入浅出RxJava(二:オペレータ)

5883 ワード

最初のblogでは、RxJavaの基礎知識を紹介し、map()オペレータも紹介しました.もちろん、RxJavaを使う気がなければ、私は少しも驚いていません.結局、この点に触れました.このblogを見て、私はあなたがすぐにあなたのプロジェクトでRxJavaを使用したいと信じています.このblogは多くのRxJavaのオペレータを紹介します.RxJavaの強さは定義されたオペレータから来ています.
まず例を見てみましょう
準備作業
私にはこのような方法があるとします.
この方法は入力した文字列に基づいて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の特性を破壊します.
改善
救いの星が来た.彼は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ではなく、Observableのような単一の文字列を受信しました.from()の出力は同じです.
この部分も私がRxJavaを初めて学んだときに最も理解しにくい部分で、私が突然悟ったら、RxJavaの多くの疑問も一緒に解決しました.
もっといい
flatMap()は、戻りたいObservableオブジェクトを返すことができます.
たとえば、次の方法があります.

//        ,  404    null  
Observable<String> getTitle(String URL);

次に前の例では、URLを印刷したくないのではなく、受け取った各サイトのタイトルを印刷します.質問ですが、私の方法は毎回1つの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オブジェクトを返す方法を組み合わせることができます!かっこいい!
それだけでなく、2つのAPIの呼び出しを1つのチェーン呼び出しに組み合わせました.任意の複数のAPI呼び出しをリンクすることができます.すべてのAPI呼び出しを同期し、すべてのAPI呼び出しのコールバック結果を表示する必要があるデータに組み合わせることがどんなに卵痛であるかを知っておく必要があります.ここではcallback hell(多層ネストされたコールバックにより、コードの読み取りとメンテナンスが困難になる)を回避することに成功しました.現在、すべての論理がこのような簡単な応答呼び出しにパッケージされています.
豊富なオペレータ
これまで2つのオペレータに接触してきましたが、RxJavaにはもっと多くのオペレータがあります.では、他のオペレータを使用してコードを改善するにはどうすればいいのでしょうか.
gettitle()はurlが存在しない場合nullを返します.「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));

フィルタ()は入力と同じ要素を出力し、検査条件を満たさないものをフィルタします.
最大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の威力を完全に把握します.
カスタムオペレータを書くこともできます!このブログではカスタムオペレータを使うつもりはありませんが、あなたが望むなら、自分でGoogleをクリアしましょう.
気分はどうですか.
あなたは懐疑主義者で説得しにくいのに、なぜこれらのオペレータに関心を持っているのでしょうか.
オペレータはデータストリームを操作できるからです.
一連のオペレータをリンクすると複雑な論理が完了します.コードは一連の組み合わせ可能なセグメントに分解される.これが応答式関数プログラミングの魅力です.多ければ多いほど、プログラミングの思考が変わります.
また、RxJavaは、データの処理方法をより簡単にします.最後の例では、2つのAPIを呼び出し、APIが返すデータを処理してディスクに保存します.しかし、私たちのSubscriberはこれらを知らないで、それはただ自分がObservableオブジェクトを受信していると思っています.良好なパッケージ性もコードの便利さをもたらしました!
第3部では、エラー処理や同時実行など、RxJavaの他のクールな特性について説明します.これらの特性はデータの処理に直接使用されません.
テキストリンク