[英]rxJava2 Combining Single, Maybe, Completable in complex Streams
我对新的RxJava Sources
非常兴奋,例如: Single
, Maybe
, Completable
,这使得你的接口类更清晰,并防止在创建你的'Source'时出现很多错误(例如忘记调用onComplete()
)
但它需要大量的样板才能将它们组合成一个复杂的流。
例如,我们有加载和缓存数据的常见Android情况。 假设我们有2个源api
和cache
,我们希望将它组合起来:
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();
所以我没有看到任何方法来使用新的源代码而没有很多转换会增加代码噪声并创建大量额外的对象。
由于这些问题,我无法使用Single
, Maybe
, Completable
并继续使用Observable
。
所以我的问题是:
结合Single
, Maybe
, Completable
的最佳实践是什么?
为什么这些Source没有重载来简化梳理。
为什么这些来源没有共同的祖先并将其用作
switchIfEmpty
参数和其他方法?
PS有谁知道为什么这些类没有任何共同的层次结构?
从我的角度来看,如果某些代码可以用例如Completable
那么Single
和Maybe
也能正常工作吗?
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团队通过为Maybe
, Single
, Observable
添加额外的重载来完成这项工作,简化了将它们组合在一起的过程。
至于版本2.1.16,我们有以下方法用于组合Maybe
, Single
和Completable
:
也许 : flatMapSingleElement(Single):Maybe
, flatMapSingle(Single):Single
, switchIfEmpty(Single):Maybe
, flatMapCompletable(Completable):Completable
单一 : flatMapMaybe(Maybe):Maybe
, flatMapCompletable(Completable):Completable
可完成 : andThen(Single):Single
, andThen(Maybe):Maybe
我知道这个问题已经过时了,但似乎尚未接受答案。
从RxJava 2.1.4开始,他们最终添加:
public final Single<T> switchIfEmpty(SingleSource<? extends T> other)
所以你可以简化你的链:
cache.switchIfEmpty(api)
如果你有最新版本的RxJava,这应该是这种情况的首选方式。 请注意,该方法是使用@Experimental
注释的,因此将来可能会再次更改。
也许我不是一个全面的答案,但我试着回答你的具体用例:
我认为你的组合任务的目的是从缓存中获取数据,如果结果是空的,你想调用远程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);
}
});
我没有测试它,但我认为可能是一个可能的解决方案(不确定是否最好)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.