Rx いいよ Rx とか言っておきながら、いままで Cold と Hot の違いについて、ちゃんとわかってませんでしたスイマセン。
そのため、
で作ったサンプルプログラム、盛大にバグってましたorz
音楽プレーヤ 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() を Observable のおしりにくっつけます。はい、これだけ。本当に。簡単すぎて「いいの?」って思っちゃうくらい。
``java getCurrectLocationAsHotObservable.java /**
*/
public static ObservableBuilder
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](http://reactive4java.googlecode.com/svn/trunk/Reactive4Java/docs/javadoc/index.html) では、``publish`` は、普通の ``Observable<T>`` を返します。Observable には register(.NET の Subscribe に相当)しかないので、これを呼び出した時に再生が開始されます。
特に reactive4java の挙動で困っていませんが、今後のバージョンアップで .NET 側に合わせられるかも知れません。
ConnecableObservable という interface は既に用意されていますが、使われていないようです。
## 参考
* [Rx入門 (14) – Cold to Hot変換 : xin9le note](http://xin9le.net/archives/104)
* [Reactive Extensions再入門 その36「ColdからHotへ!Publishメソッドと参照カウンタ?RefCountメソッド」 - かずきのBlog@Hatena](http://d.hatena.ne.jp/okazuki/20120212/1329059831)
* [neue cc - Reactive Extensions for .NET (Rx) メソッド探訪第7回:IEnumerable vs IObservable](http://neue.cc/2010/06/24_263.html)
Rx の神々のみなさんが懇切丁寧に解説してくださってるのに、失敗しないと気づかない自分のバカバカ!