Rx いいよ Rx とか言っておきながら、いままで Cold と Hot の違いについて、ちゃんとわかってませんでしたスイマセン。

そのため、

で作ったサンプルプログラム、盛大にバグってましたorz

Cold な Observable と Hot な Observable

音楽プレーヤ iPod に例えると自分なりにしっくり来ました。
Observable が iPod で、Observer は聴く人。
なんとこの iPod はイヤホンジャックがたくさんあります。
そしてさらにこの iPod はイヤホンを接続するだけで再生が始まり、抜くと停止します。

Cold な iPod では、聴く人がイヤホンを接続すると、音楽が最初から再生されます。
次の人がイヤホンを接続すると、また音楽が最初から再生されます。(最初の人は、再生されなおすわけじゃないよ。)

Hot な iPod では、最初に聴く人がイヤホンを接続すると、音楽が再生され始めます。
次の人が、イヤホンを接続すると、その人は途中から聴くことになります。一つのストリーミング放送をみんなで聴くみたいな。
最後の人がイヤホンを外すと、再生が止まります(この辺はストリーミングと微妙に感覚が異なる、ストリーミングって、聴いてる人が居ようが居まいが流され続けるってイメージだから)。

何が問題か

以上を踏まえた上で、reactive4java で位置を取得し続ける - Qiita で作ったプログラムのどこが問題だったかというと。

位置を聞くために接続をすると、その都度、locMan.requestLocationUpdates が呼ばれているという事です。上記の音楽プレーヤで例えると、player.start() です。

位置情報の取得は、ホントに無限ストリーミングなので、一見問題無さげに見えますが、2つリスナを登録するのは頂けません。(中には複数のリスナを登録できない API もあるでしょう、ありました。それで気づいたんです。)

これは最初の register でのみ locMan.requestLocationUpdates が実行され、2番目以降の register では、observer.next だけが呼ばれるようにしないといけません。
そのためには、register した複数の observer を保持・管理する必要があります。うげー。

そこで Publish ですよ。

.publish() を Observable のおしりにくっつけます。はい、これだけ。本当に。簡単すぎて「いいの?」って思っちゃうくらい。

``java getCurrectLocationAsHotObservable.java
/**

  • 位置を取得し続ける(Hot)
    */
    public static ObservableBuilder getCurrentLocationAsHotObservable( final Context context, final String provider) { return ObservableBuilder.from( getCurrentlocationAsObservable(context, provider) ).publish(); // Cold → Hot へ変換! } ```

これだけで、複数の人が位置を聴きに来ても、locMan.requestLocationUpdates が呼ばれるのは1回だけである、Hot な Observable になります。Rx すげえよ Rx!

reactive4java のソースを読んだところ、前述の「複数の observer を保持・管理して、最初だけリスナ登録して、誰もいなくなったらリスナ解除する」みたいな面倒なことを publish の中(正確には observeOn)で行なってくれているようです。

ますます Reactive Extensions が好きになりましたよ。

.NET の Reactive Extensions と reactive4java の違い

.NET の Reactive Extenstions では、Publish は、IConnectableObservable<T> を返すそうです。そして Subscribe しただけでは再生は開始されず、Connect した時に再生されるのだ、とも。

一方、reactive4java では、publish は、普通の Observable<T> を返します。Observable には register(.NET の Subscribe に相当)しかないので、これを呼び出した時に再生が開始されます。

特に reactive4java の挙動で困っていませんが、今後のバージョンアップで .NET 側に合わせられるかも知れません。
ConnecableObservable という interface は既に用意されていますが、使われていないようです。

参考

Rx の神々のみなさんが懇切丁寧に解説してくださってるのに、失敗しないと気づかない自分のバカバカ!

amay077

Microsoft MVP(Xamarin). フルリモートワーカー. Geospatial Mobile app developer. Love C#.

amay077 amay077