使用其他 Observable 过滤 RxJava Observable

Filter RxJava Observable with other Observable

我正在使用 RxAndroid 2.0.1 和 RxJava 2.0.6。

我有两个可观察对象:一个 returns Maybe<MyObject> 基于一些字符串 (ID)。当可选对象被 returned 时,如果对象满足某些条件,我必须调用第二个采用 MyObject 实例和 returns 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 不能被订阅直到第一个 returns MyObject

  2. 尝试使用 filter - 现在的问题是我需要使用阻塞 get 来调用第二个可观察对象。它可能会工作,但看起来像代码味道:

    objectDAO.getById(objectId)
      .filter(myObject ->
        otherDAO.checkCondition(myObject).blockingGet()
      )
      .subscribe(
          myObject -> checkCondition(myObject),
          throwable -> /* Fallback */,
          () -> /* Fallback */
      );
    
  3. 尝试使用 flatMap - 第二个可观察的 returns 布尔值,而我需要 return 原始对象。因此,我需要使用 blockingGet 和 return 原始对象或 Maybe.empty()

  4. 映射代码片段

关于如何以代码 "clean" 的方式进行操作的任何建议(它更小,但仍然清楚内部发生了什么)?

你可以做的一件事:

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

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

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

我想出了解决方案,但没有传递布尔值对,以防有人遇到同样的问题。 比如objectDAO.getById(objectId)returnsObservable<T>otherDAO.checkCondition(myObject)returnsSingle<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 -> ...)