web-dev-qa-db-ja.com

複雑なストリームで単一、多分、完成可能なrxJava2を組み合わせる

新しいRxJava Sourcesのような、SingleMaybeCompletableを使用すると、インターフェイスクラスがよりクリーンになり、「ソース」の作成時の多くのミスを防ぐことができます(たとえば、onComplete()を呼び出すのを忘れる)

しかし、それらを複雑なストリームに組み合わせるには、多くのボイラープレートが必要です。

例えば。 Androidデータのロードとキャッシュの状況があります。2つのソースapicacheがあり、それらを組み合わせたいとしましょう:

_public interface Api {
    Single<Integer> loadFromNetwork();
}

public interface Cache {
    Maybe<Integer> loadFromCache(); //maybe because cache might not have item.
}
_

それを組み合わせてみましょう:

_final Single<Integer> result = cache.loadFromCache()
        .switchIfEmpty(api.loadFromNetwork());
_

Maybeにはオーバーロードがないため、コンパイルされませんMaybe.switchIfEmpty(Single):Single

したがって、すべてを変換する必要があります。

_final Single<Integer> result = cache.loadFromCache()
        .switchIfEmpty(api.loadFromNetwork().toMaybe())
        .toSingle();
_

それを組み合わせるもう1つの可能な方法も、バージョンの変換が必要です。

_final Single<Integer> result = Observable.concat(
            cache.loadFromCache().toObservable(),
            api.loadFromNetwork().toObservable()
        ).firstOrError();
_

したがって、コードノイズを追加し、多くの追加オブジェクトを作成する多くの変換なしに、新しいソースを使用する方法はありません。

そのような問題のため、SingleMaybeCompletableを使用できず、どこでもObservableを引き続き使用できません。

だから私の質問は:

  • SingleMaybeCompletableを組み合わせる際のベストプラクティスは何ですか。

  • コーミングを容易にするためにこれらのソースにオーバーロードがないのはなぜですか。

  • これらのソースに共通の祖先がなく、それを次のように使用する理由
    switchIfEmptyおよびその他のメソッドのパラメータ?


PSこれらのクラスに共通の階層がない理由を誰かが知っていますか?
たとえば、Completableで動作するコードがある場合、SingleおよびMaybeでも正常に動作しますか?

13

RxJava 2.1.4 2017年9月22日にリリースされ、必要なオーバーロードMaybe.switchIfEmpty(Single):Singleが追加されました。

したがって、以下のクラスを組み合わせる場合は、

_public interface Api {
    Single<Integer> loadFromNetwork();
}

public interface Cache {
    Maybe<Integer> loadFromCache(); //maybe because cache might not have item.
}
_

ようやくできます:

_final Single<Integer> result = cache.loadFromCache()
        .switchIfEmpty(api.loadFromNetwork());
_

Rxチームは、MaybeSingleObservableに追加のオーバーロードを追加することで素晴らしい仕事をしました。

リリースについては 2.1.16MaybeSingleおよびCompletableを組み合わせるための次のメソッドがあります。

たぶんflatMapSingleElement(Single):MaybeflatMapSingle(Single):SingleswitchIfEmpty(Single):MaybeflatMapCompletable(Completable):Completable

シングルflatMapMaybe(Maybe):MaybeflatMapCompletable(Completable):Completable

完了可能andThen(Single):SingleandThen(Maybe):Maybe

5

質問はもう古いですが、まだ受け入れられていないようです。

RxJava 2.1.4以降、最終的に次のものを追加します。

public final Single<T> switchIfEmpty(SingleSource<? extends T> other)

したがって、チェーンを単純化して次のようにすることができます。

cache.switchIfEmpty(api)

最新バージョンのRxJavaを使用している場合は、この方法をお勧めします。このメソッドには@Experimentalの注釈が付けられているため、将来再び変更される可能性があることに注意してください。

2

多分私は包括的な答えではありませんが、あなたの特定のユースケースに答えようとします:

結合タスクの目的は、キャッシュからデータをフェッチすることであると思います。結果が空の場合は、リモートAPIを呼び出します。

    final Single<List<Integer>> single = api.call();
    Maybe<List<Integer>> maybe = disk.call();


    Single <List<Integer>> composedSingle = maybe.flatMapSingle(new Function<List<Integer>, SingleSource<?>>() {
        @Override
        public SingleSource<?> apply(List<Integer> integers) throws Exception {
            if(integers.isEmpty()) return single;
            else return Single.just(integers);
        }
    });

私はそれをテストしていませんが、可能な解決策になる可能性があると思います(最善かどうかはわかりません)。

0
Fabio