22時に寝ようと思って2時に寝る。

備忘録や日記を書いてます。きょうは早く寝よう。

RxJava - オペレータについて

今回は、Publisher から通知されたデータを受け取って処理する際に用いるオペレータを見ていきます。

段階的にデータを整形する

RxJava では、Publisher(Flowable / Observable)から Subscriber(Subscriber / Observer)にデータが通知される間に Subscriber がデータを利用しやすい形に整形、変換することができます。整形されたデータは再び Flowable / Observable なデータとして返されるため、メソッドチェインする形で段階的にデータを整形することが可能です。こういったデータを生成したり、変換したり、フィルターをかけたりできるメソッドのことを RxJava ではオペレータと呼びます。

メソッドをつなげて Subscriber へ通知されていく流れ

f:id:azuuun:20180818001129p:plain

上記の図は、流れてきた数値データを x5 していくオペレータのイメージ図です。丸い円のことをマーブルと呼んだりします。これをコードで表記すると以下のようになります。

public static void main(String[] args) {
    Flowable<Integer> flowable =
        // 1 から 10 までの数値を順に通知していくデータを生成
        Flowable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        // 通知するデータを 5 倍していく
        .map(data -> data * 5);
        
    flowable.subscribe(data -> System.out.println("data=" + data));
}

期待される実行結果は以下です。

data=5
data=10
data=15
...
data=45
data=50

おおまかな順序は以下のとおりです。

  1. just メソッドを用いて、引数通して渡した左から順番にデータを通知していく Flowable を生成する
  2. map メソッドを用いて、 Flowable によって通知されてきたデータを一つずつ 5 倍する

このように通知されてきたデータを一気に処理していくのではなく、オペレータを使用して Observable を返しながら 最終的に通知したいデータへ制御できます。

関数型インタフェースに影響を受けた RxJava

RxJava はメソッドの多くが関数型インタフェースを引数として受け取るようになっており、関数型プログラミングの原則に従い、

  • 同じ入力を受け取ったら毎回同じ結果を返す
  • 入力値や処理の外部のオブジェクトおよび環境に対して何も変化を起こさない

以上の2つが基本となります。

副作用を避ける

オペレータによって受け取ったデータの状態に変化を与えたり、外部に対して何らかの変化を与えたりすることを副作用と呼びます。処理の外部から参照型のオブジェクトの値を変える、データベースやファイルを更新するといったものが、副作用にあたります。副作用を避けることによって、責任範囲がより明確になります。このことより、以下のことが期待できます。

  • 複数のスレッドから参照されるオブジェクトがないため、スレッドセーフになる
  • 仮にある実装がパフォーマンス改善のために同期処理から非同期処理に置き換わったとしても、内部の処理は修正せずに動き続ける

データの処理のタイミングに注意する

関数型プログラミングでは、引数で渡したデータはその時点で評価された値を受け取ります。引数に式を記述したとしても、既に評価された値しか渡されません。つまり、メソッドが実行される前から値が決まっています。

例として以下のコードでは、Flowable が生成された際にシステム時間が評価され、値が確定します。

Flowable<Long> flowable =
    Flowable.just(System.currentTimeMillis());

一方で、以下のコードでは購読されたタイミングでfromCallbackメソッドが呼び出され、呼び出された瞬間にシステムの時間が決定され通知されます。

print(() -> System.currentTimeMills());

つまり、

  • justメソッドによるデータを通知する Flowable を何度 onSubscribe で購読したとしても同じ値を返す
  • 一方で fromCallBack メソッドによって生成された Flowable は呼び出すたびに式が評価され値が変化する

次の記事

azunobu.hatenablog.com

参考

RxJavaリアクティブプログラミング (CodeZine BOOKS)

RxJavaリアクティブプログラミング (CodeZine BOOKS)