RxJavaでオブザーバブルを結合する
1. 前書き
このクイックチュートリアルでは、RxJavaでObservablesを組み合わせるさまざまな方法について説明します。
RxJavaを初めて使用する場合は、まずこのintro tutorialを確認してください。
それでは、すぐに始めましょう。
2. Observables
Observableシーケンス、または単にObservablesは、非同期データストリームの表現です。
これらはObserver patternに基づいており、Observerと呼ばれるオブジェクトがObservableによって発行されたアイテムをサブスクライブします。
Observerは、Observableが将来放出するものに反応するため、サブスクリプションは非ブロッキングです。 これにより、並行性が促進されます。
RxJavaでの簡単なデモンストレーションは次のとおりです。
Observable
.from(new String[] { "John", "Doe" })
.subscribe(name -> System.out.println("Hello " + name))
3. オブザーバブルの組み合わせ
リアクティブフレームワークを使用してプログラミングする場合、さまざまなObservablesを組み合わせるのが一般的なユースケースです。
たとえば、Webアプリケーションでは、互いに独立した2セットの非同期データストリームを取得する必要がある場合があります。
次のストリームを要求する前に前のストリームが完了するのを待つ代わりに、両方を同時に呼び出して、結合されたストリームをサブスクライブすることができます。
このセクションでは、RxJavaで複数のObservablesを組み合わせることができるいくつかのさまざまな方法と、各方法が適用されるさまざまなユースケースについて説明します。
3.1. Merge
merge演算子を使用して、複数のObservablesの出力を組み合わせて、1つのように機能させることができます。
@Test
public void givenTwoObservables_whenMerged_shouldEmitCombinedResults() {
TestSubscriber testSubscriber = new TestSubscriber<>();
Observable.merge(
Observable.from(new String[] {"Hello", "World"}),
Observable.from(new String[] {"I love", "RxJava"})
).subscribe(testSubscriber);
testSubscriber.assertValues("Hello", "World", "I love", "RxJava");
}
3.2. MergeDelayError
mergeDelayErrorメソッドは、複数のObservablesを1つに結合するという点で、mergeと同じですが、if errors occur during the merge, it allows error-free items to continue before propagating the errorsは次のようになります。
@Test
public void givenMutipleObservablesOneThrows_whenMerged_thenCombineBeforePropagatingError() {
TestSubscriber testSubscriber = new TestSubscriber<>();
Observable.mergeDelayError(
Observable.from(new String[] { "hello", "world" }),
Observable.error(new RuntimeException("Some exception")),
Observable.from(new String[] { "rxjava" })
).subscribe(testSubscriber);
testSubscriber.assertValues("hello", "world", "rxjava");
testSubscriber.assertError(RuntimeException.class);
}
上記の例emits all the error-free values:
hello
world
rxjava
mergeDelayErrorの代わりにmergeを使用する場合、mergeはObservablesエラー発生時。
3.3. Zip
zip拡張メソッドbrings together two sequences of values as pairs:
@Test
public void givenTwoObservables_whenZipped_thenReturnCombinedResults() {
List zippedStrings = new ArrayList<>();
Observable.zip(
Observable.from(new String[] { "Simple", "Moderate", "Complex" }),
Observable.from(new String[] { "Solutions", "Success", "Hierarchy"}),
(str1, str2) -> str1 + " " + str2).subscribe(zippedStrings::add);
assertThat(zippedStrings).isNotEmpty();
assertThat(zippedStrings.size()).isEqualTo(3);
assertThat(zippedStrings).contains("Simple Solutions", "Moderate Success", "Complex Hierarchy");
}
3.4. 間隔を置いて圧縮する
この例では、intervalを使用してストリームを圧縮します。これにより、実際には最初のストリームの要素の放出が遅延します。
@Test
public void givenAStream_whenZippedWithInterval_shouldDelayStreamEmmission() {
TestSubscriber testSubscriber = new TestSubscriber<>();
Observable data = Observable.just("one", "two", "three", "four", "five");
Observable interval = Observable.interval(1L, TimeUnit.SECONDS);
Observable
.zip(data, interval, (strData, tick) -> String.format("[%d]=%s", tick, strData))
.toBlocking().subscribe(testSubscriber);
testSubscriber.assertCompleted();
testSubscriber.assertValueCount(5);
testSubscriber.assertValues("[0]=one", "[1]=two", "[2]=three", "[3]=four", "[4]=five");
}
4. 概要
この記事では、ObservablesをRxJavaと組み合わせる方法をいくつか見てきました。 official RxJava documentationで、combineLatest、join、groupJoin、switchOnNextなどの他のメソッドについて学ぶことができます。
いつものように、この記事のソースコードはGitHub repoで入手できます。