rxJava2 在复杂流中组合单一的、可能的、可完成的

rxJava2 Combining Single, Maybe, Completable in complex Streams

我对新的 RxJava Sources 感到非常兴奋,例如:SingleMaybeCompletable,它使您的界面 类 更干净并防止在创建 'Source' 过程中犯了很多错误(例如忘记调用 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();

另一种可能的组合方式也需要 сonversion:

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

因此,如果不进行许多会增加代码噪音并创建大量额外对象的转换,我看不出有任何方法可以使用新源。

由于这些问题,我无法使用 SingleMaybeCompletable 并继续到处使用 Observable

所以我的问题是:


P.S. 有人知道为什么这些 类 没有任何共同的层次结构吗?
从我的角度来看,如果某些代码可以与 Completable 一起工作,它也可以与 SingleMaybe?

一起工作

也许我不是一个全面的答案,但我试着回答你的具体用例:

我认为你的合并任务的目的是从缓存中获取数据,如果结果为空你想调用远程 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);
        }
    });

我没有测试过,但我认为可能是一个可能的解决方案(不确定是否最好)。

我知道这个问题已经很老了,但似乎还没有公认的答案。

从 RxJava 2.1.4 开始,他们最终添加:

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

因此您可以将链简化为:

cache.switchIfEmpty(api)

如果你有最新版本的 RxJava,这应该是这种情况的首选方法。请注意,该方法带有 @Experimental 注释,因此将来可能会再次更改。

2017 年 9 月 22 日发布的 RxJava 2.1.4 添加了所需的重载 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.16,我们有以下组合MaybeSingleCompletable的方法:

可能: flatMapSingleElement(Single):Maybe, flatMapSingle(Single):Single, switchIfEmpty(Single):Maybe, flatMapCompletable(Completable):Completable

单身: flatMapMaybe(Maybe):Maybe, flatMapCompletable(Completable):Completable

可完成: andThen(Single):Single, andThen(Maybe):Maybe