web-dev-qa-db-ja.com

RxJava-Observable.share()を使用する時期と理由

私はこのようなパターンを見てきました:

_Observable<String> nameChanges = nameDataSource.changes().share();

// One subscriber
autoUnsubscribe(nameChanges.subscribe(() -> { ... }));

// Another subscriber
autoUnsubscribe(nameChanges.map(...).filter(...).subscribe(...));

// autoUnsubscribe is called when the UI is torn down
_

私の質問は:

複数の場所でObservableを聴きたいときに、なぜshare()を呼び出す必要があるのですか?


share()がすべてのオブザーバブルのデフォルトの動作ではないのはなぜですか?

上記のコードが.share()がなくても同じように機能するのは素晴らしいことです。いつObservableを共有する必要があるのか​​、いつ共有しないのかを考える必要はありません。

単一のサブスクライバーを持つことは、より効率的に処理できる特殊なケースであるため、パフォーマンス上の理由ですか?

ドキュメントから、これは私には明らかではありません:

share()は、元のObservableSourceをマルチキャスト(共有)する新しいObservableSourceを返します。少なくとも1つのオブザーバーが存在する限り、このObservableSourceはサブスクライブされ、データを発行します。

enter image description here

11
Martin Konicek

Observablesには、コールドとホットの2種類があります。 ColdObservablesは、Observerが存在するときにアイテムの作成を開始し、個別に作成します。複数のObserversでサブスクライブすると、同じコールドObservableが複数回実行されます。この例は、ネットワーク要求を発行するObservableです。

対照的に、hotObservableは、Observersの存在の有無にかかわらずアイテムを生成できます。これらのObservablesは通常、同じアイテムを現在のすべてのObserversにマルチキャストします。この例は、ボタンクリックのObservableです。

コールドObservableをホットなものに変えるには、publish()を使用できます。これにより、Observableの数に関係なく、ソースObserverに対して単一のサブスクリプションのみが確立されます。 $ var] _sあります。したがって、チェーンはObservablesの観点からホットマルチキャストObserverとして機能するようになります。

ただし、多くの場合、publish()のすべてのObservableがなくなった後、元のコールドObserverを実行し続けることは経済的ではないため、refCount()演算子は次のことができます。それらを追跡し、興味深いパーティが残っていないときにソースを停止するために使用されます。

ソースがすでにホットな場合は、share()は必要ありません。

Share()がすべてのオブザーバブルのデフォルトの動作ではないのはなぜですか?

実際、このプロパティは、最新のリアクティブプログラミングパラダイムの重要な貢献の1つです。つまり、ホットとコールドのObservablesの区別です。

ただし、マルチキャストは、新しいイベントを通知するために現在のObserverのセットを追跡する必要があるため、それ自体がコストがかかります。これにより、あらゆる種類の論理的な競合状態を防ぐことができます。コールドObservableは単一のObserverとのみ通信することが知られているため、追加のトラッキングオーバーヘッドは必要ありません。

20
akarnokd

I would not have to think about when I need to share an Observable, and when I don't.プログラミングの際に考えなければならないのではないかと思います。 ;)

上記のコードでは、はい、共有は理にかなっています。しかし、2つの異なるポイントから同じネットワークとメソッド呼び出しを使用し、異なるデータで更新して、バックエンドで何かを更新している場合はどうなるでしょうか。同じObservableで同じ呼び出しがありますが、確かにそうしません Observableインスタンス(およびネットワーク呼び出し)を共有したいのは、データを含むすべての連続する呼び出しがで破棄されることを意味するためです。最初のものの好意。または、サブスクライブしているときにタイマーを開始したい場合は、これを他のObservablesと共有したくないでしょう。

また、追加特定の動作は削除よりもはるかに簡単です。たとえば、共有がデフォルトであり、2番目のサブスクライバーが共有を望まず、共有を削除した場合、3番目のサブスクライバーはどうでしょうか。最初のものと共有しますか?その時点で、共有プロパティはSubscriberではなくObservableのプロパティになり、どちらが共有され、どれが共有されていないかを明確に知る方法がありません。

1
Sasa Sekulic