【问题标题】:rxJava2 Combining Single, Maybe, Completable in complex StreamsrxJava2 在复杂流中结合 Single、Maybe、Completable
【发布时间】:2017-07-26 15:39:56
【问题描述】:

我对新的 RxJava Sources 感到非常兴奋,例如:Single、Maybe、Completable,它使您的接口类更清晰,并防止在创建“源”(例如忘记打电话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。

  • 为什么这些来源没有重载以使梳理更容易。

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


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

【问题讨论】:

  • 我认为this 涵盖了除最佳实践之外的所有内容。如果您需要 switchIfEmptySingle 之类的方法,也许您可​​以要求它。
  • 当一个项目在缓存中不可用并且您从网络加载它时,您是否希望网络调用也更新缓存数据?我的意思是,你为什么要将两者结合起来?假设您有一个缓存存储,例如一个房间数据库,并且您观察到一个带有 Flowable 的表,如果没有任何特定于您的查询的内容,则不会发出此流。同时你发送一个请求,如果有数据返回,当你把它放到你的表中时,Flowable 会发出不同的结果。

标签: java android rx-java rx-java2


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    因此您可以将链简化为:

    cache.switchIfEmpty(api)
    

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 如果可能只是简单地完成而不发射,flatMapSingle 将抛出异常。
      • 是的,你是对的。所以我应该完全删除建议的解决方案和答案?
      • 建议代码中还有另一个问题:空列表不是表明缓存中没有此类项目的最佳方式,因为它不允许正确缓存来自服务器的空响应。跨度>
      猜你喜欢
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-23
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多