RxJava Completablesの組み合わせ
1. 概要
このチュートリアルでは、RxJava’sCompletableタイプを試してみます。これは、実際の値のない計算結果を表します。
2. RxJavaの依存関係
RxJava2の依存関係をMavenプロジェクトに含めましょう。
io.reactivex.rxjava2
rxjava
2.2.2
通常、最新バージョンはMaven Centralで見つけることができます。
3. 完成可能なタイプ
Completableis similar to Observable with the only exception that the former emits either completion or error signals but no items.Completable クラスには、さまざまなリアクティブソースから作成または取得するための便利なメソッドがいくつか含まれています。
Completable.complete()を使用すると、すぐに完了するインスタンスを生成できます。
次に、DisposableCompletableObserverを使用してその状態を観察できます。
Completable
.complete()
.subscribe(new DisposableCompletableObserver() {
@Override
public void onComplete() {
System.out.println("Completed!");
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
});
さらに、Callable, Action, and RunnableからCompletableインスタンスを作成できます。
Completable.fromRunnable(() -> {});
また、Completable.from()を使用するか、Maybe、Single、Flowable、およびObservableソース自体:
Flowable flowable = Flowable
.just("request received", "user logged in");
Completable flowableCompletable = Completable
.fromPublisher(flowable);
Completable singleCompletable = Single.just(1)
.ignoreElement();
4. チェーンCompletables
操作の成功のみを重視する場合、多くの実際のユースケースでCompletablesのチェーンを採用できます。
-
PUTリクエストを実行してリモートオブジェクトを更新し、成功するとローカルデータベースを更新するなどのオールオアナッシングアクション
-
事後ログおよびジャーナリング
-
いくつかのアクションのオーケストレーション、例えば 取り込みアクションが完了した後に分析ジョブを実行する
例はシンプルで問題にとらわれないものにしておきます。 いくつかのCompletableインスタンスがあるとします。
Completable first = Completable
.fromSingle(Single.just(1));
Completable second = Completable
.fromRunnable(() -> {});
Throwable throwable = new RuntimeException();
Completable error = Single.error(throwable)
.ignoreElement();
To combine two Completables into a single one, we can use the andThen() operator:
first
.andThen(second)
.test()
.assertComplete();
必要な数のCompletablesをチェーンできます。 同時に、if at least one of the sources fails to complete, resulting Completable won’t fire onComplete() as well:
first
.andThen(second)
.andThen(error)
.test()
.assertError(throwable);
さらに、if one of the sources is infinite or doesn’t reach onComplete for some reason, the resulting Completable will never fire onComplete() nor onError() as well.
このシナリオを引き続きテストできることは良いことです。
...
.andThen(Completable.never())
.test()
.assertNotComplete();
5. 一連のコンプリートを作成する
たくさんのCompletables.があると想像してください。実際のユースケースとして、いくつかの別々のサブシステム内にユーザーを登録する必要があると仮定します。
To join all Completables into a single one, we can use the merge() family of methods.merge()演算子を使用すると、すべてのソースにサブスクライブできます。
結果のインスタンスcompletes once all of the sources are completed。 さらに、ソースのいずれかがエラーを発行すると、onErrorで終了します。
Completable.mergeArray(first, second)
.test()
.assertComplete();
Completable.mergeArray(first, second, error)
.test()
.assertError(throwable);
少し異なるユースケースに移りましょう。 Flowable.から取得したすべての要素に対してアクションを実行する必要があるとします。
次に、アップストリームの完了とすべての要素レベルのアクションの両方に単一のCompletableが必要です。 この場合、flatMapCompletable()演算子が役立ちます。
Completable allElementsCompletable = Flowable
.just("request received", "user logged in")
.flatMapCompletable(message -> Completable
.fromRunnable(() -> System.out.println(message))
);
allElementsCompletable
.test()
.assertComplete();
同様に、上記のメソッドは、Observable、Maybe、Single.などの残りの基本反応クラスで使用できます。
flatMapCompletable()の実際的なコンテキストとして、すべてのアイテムを何らかの副作用で装飾することを考えることができます。 完了した要素ごとにログエントリを書き込むか、アクションが成功するたびにストレージスナップショットを作成できます。
最後に、we may need to construct a Completable from a couple of other sources and get it terminated as soon as either of them completes.は、ambの演算子が役立つ場所です。
ambプレフィックスは「あいまい」の省略形であり、どのCompletableが正確に完了するかについての不確実性を意味します。 例:ambArray():
Completable.ambArray(first, Completable.never(), second)
.test()
.assertComplete();
上記のCompletable は、完了可能なソースが最初に終了する場合によっては、onComplete()ではなくonError()で終了する場合があることに注意してください。
Completable.ambArray(error, first, second)
.test()
.assertError(throwable);
また、最初のソースが終了すると、残りのソースは破棄されることが保証されます。
つまり、残りの実行中のすべてのCompletablesはDisposable.dispose()を介して停止され、対応するCompletableObserversはサブスクライブ解除されます。
実際の例に関しては、バックアップファイルをいくつかの同等のリモートストレージにストリーミングするときにamb()を使用できます。 そして、最初の最適なバックアップが終了したらプロセスを完了するか、エラーが発生したときにプロセスを繰り返します。
6. 結論
この記事では、RxJavaのCompletable typeについて簡単に説明しました。
Completableインスタンスを取得するためのさまざまなオプションから始めて、andThen(), merge(), flatMapCompletable(), およびamb…()演算子を使用してCompletablesをチェーンおよび構成しました。
すべてのコードサンプルover on GitHubのソースを見つけることができます。