rxJava2在复杂流中组合Single,Maybe,Completable

时间:2017-07-26 15:39:57

标签: java android rx-java rx-java2

我对新的RxJava Sources感到非常兴奋,例如:SingleMaybeCompletable,这使您的界面类更清晰,并防止在此期间出现大量错误创建您的“来源”(例如忘记致电onComplete()

但它需要大量的样板才能将它们组合成一个复杂的流。

E.g。我们有常见的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

所以我的问题是:

  • 合并SingleMaybe的最佳做法是什么, Completable

  • 为什么这些来源没有重载来简化梳理。

  • 为什么这些来源没有共同的祖先并将其用作
    参数switchIfEmpty和其他方法?

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

3 个答案:

答案 0 :(得分:4)

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):MaybeflatMapSingle(Single):SingleswitchIfEmpty(Single):MaybeflatMapCompletable(Completable):Completable

flatMapMaybe(Maybe):MaybeflatMapCompletable(Completable):Completable

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

答案 1 :(得分:2)

我知道这个问题已经很老了,但似乎尚未被接受。

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

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

因此您可以将连锁简化为:

cache.switchIfEmpty(api)

如果您具有最新版本的RxJava,则应该是这种情况的首选方法。请注意,该方法使用@Experimental进行了注释,因此将来可能会再次更改。

答案 2 :(得分:0)

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

我认为你的组合任务的目的是从缓存中获取数据,如果结果是空的,你想调用远程api:

.foo {    
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  margin: -50px 0 0 -50px;
  background: lightblue; //not necessary of course
}

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