【问题标题】:Filter RxJava Observable with other Observable用其他 Observable 过滤 RxJava Observable
【发布时间】:2017-03-22 12:38:38
【问题描述】:

我正在使用 RxAndroid 2.0.1 和 RxJava 2.0.6。

我有两个 observable:一个基于某个字符串 (ID) 返回 Maybe<MyObject>。当返回可选对象时,如果对象满足某些条件,我必须调用第二个接受 MyObject 实例并返回 Single<Boolean> 的对象。然后我可以对对象实例做一些进一步的操作。

我目前的实现如下:

objectDAO.getById(objectId)
    .subscribe(
        myObject -> checkCondition(myObject),
        throwable -> /* Fallback */,
        () -> /* Fallback */
    );

private void checkCondition(final MyObject myObject) {
  otherDAO.checkCondition(myObject)
    .subscribe(
        isTrue -> {
          if (isTrue) {
            // yay! now I can do what I need with myObject instance
          } else {
            /* Fallback */
          }
        },
        throwable -> /* Fallback */
    );
}

现在我想知道如何简化我的代码。我的想法:

  1. 尝试使用 zip - 我不能,因为在第一个 Observable 返回 MyObject 之前无法订阅第二个 Observable

  2. 尝试使用filter - 现在的问题是我需要使用阻塞 get 来调用第二个 observable。它可以正常工作,但看起来像代码异味:

    objectDAO.getById(objectId)
      .filter(myObject ->
        otherDAO.checkCondition(myObject).blockingGet()
      )
      .subscribe(
          myObject -> checkCondition(myObject),
          throwable -> /* Fallback */,
          () -> /* Fallback */
      );
    
  3. 尝试使用flatMap - 第二个可观察对象返回布尔值,而我需要返回原始对象。因此,我需要使用blockingGet 映射代码 sn-p 并返回原始对象或Maybe.empty()

有什么建议可以让代码“干净”(它更小,而且内部发生的事情仍然很清楚)吗?

【问题讨论】:

  • objectDAO.getById(objectId).flatMap(myObject -> otherDAO.checkCondition(myObject).map(isTrue -> Pair.create(myObject, isTrue)) - 那么你有一个Observable<Pair<MyObject, Boolean>>,可以随心所欲地继续:直接订阅并检查Boolean那里,filterBoolean值等跨度>
  • @david.mihola 它类似于我的第三种方法,只是现在我意识到我不需要使用阻塞获取。所以与其返回Pair<Boolean, MyObject,我可以检查布尔值并返回Maybe.just(myObject)Maybe.empty() / Maybe.error() 仍然不确定这是否是一个好的解决方案。
  • 另外,我好像不能使用objectDAO.flatMap(otherDao.map())组合,当我把它改成objectDAO.map(otherDao.map())然后结果是Single<Maybe<Pair<Boolean, MyObject>>>这也不是很好
  • 是的,对不起 - 它叫flatMapSingle
  • 是的,我也发现我可以用flatMapSingle代替。现在我有其他问题,但与原始问题无关。请在下面粘贴您的完整答案,以便我接受:)

标签: java android rx-java rx-android rx-java2


【解决方案1】:

你可以做的一件事:

objectDAO.getById(objectId)
    .flatMapSingle(myObject -> otherDAO
        .checkCondition(myObject)
        .map(isTrue -> Pair.create(myObject, isTrue))
    )

然后你有一个Observable<Pair<MyObject, Boolean>> 并且可以随心所欲地继续:subscribe 直接检查那里的Boolean,通过布尔值检查filter,等等。

【讨论】:

    【解决方案2】:

    akarnokd 的RxJava2Extensions 额外项目有一个filterAsync 转换器(与compose 一起使用)可以做到这一点,使用任何Publisher<Boolean> ;)

    【讨论】:

      【解决方案3】:

      我已经提出了解决方案,但没有传递带有布尔值的 Pairs,以防万一有人遇到同样的问题。 比如objectDAO.getById(objectId)返回Observable<T>otherDAO.checkCondition(myObject)返回Single<Boolean>,我们可以这样处理过滤:

      objectDAO.getById(objectId)
          .flatMap(myObject -> otherDAO
              .checkCondition(myObject)
              .toObservable()
              .filter(Boolean::booleanValue)
              .map(o -> myObject))
          .flatMapSingle(obj -> ...)
      

      不需要的对象将被解析为Observable.empty并因此被过滤,这样只有需要的对象才会到达.flatMapSingle(obj -> ...)

      基本上,同样的事情可以通过稍微容易理解的结构来实现(不过,我发现第一个在美学上更好一些):

      objectDAO.getById(objectId)
          .flatMap(myObject -> otherDAO
              .checkCondition(myObject)
              .flatMapObservable(isChecked -> isChecked ? Observable.just(myObject) : Observable.empty()))
              .flatMapSingle(obj -> ...)
      

      【讨论】:

        猜你喜欢
        • 2018-06-29
        • 1970-01-01
        • 2015-08-27
        • 1970-01-01
        • 2017-10-11
        • 2019-12-18
        • 2020-09-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多