LoginSignup
6
6

More than 5 years have passed since last update.

Cold を Hot にできる。そう、Publish ならね。

Last updated at Posted at 2012-09-26

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 のおしりにくっつけます。はい、これだけ。本当に。簡単すぎて「いいの?」って思っちゃうくらい。

getCurrectLocationAsHotObservable.java
/**
 * 位置を取得し続ける(Hot)
 */
public static ObservableBuilder<Location> 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 の神々のみなさんが懇切丁寧に解説してくださってるのに、失敗しないと気づかない自分のバカバカ!

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6