使用其他Observable过滤RxJava Observable

时间:2017-03-22 12:38:39

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

我正在使用RxAndroid 2.0.1和RxJava 2.0.6。

我有两个observable:一个基于一些String(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之前无法订阅

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

    objectDAO.getById(objectId)
      .filter(myObject ->
        otherDAO.checkCondition(myObject).blockingGet()
      )
      .subscribe(
          myObject -> checkCondition(myObject),
          throwable -> /* Fallback */,
          () -> /* Fallback */
      );
    
  3. 尝试使用flatMap - 当我需要返回原始对象时,第二个observable返回布尔值。因此,我需要使用blockingGet编写代码段并返回原始对象或Maybe.empty()

  4. 有任何建议如何以这样的方式进行,即代码是“干净的”(它更小,而且仍然清楚里面发生了什么)?

3 个答案:

答案 0 :(得分:3)

你可以做的一件事:

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

然后你有一个Observable<Pair<MyObject, Boolean>>,可以直接按subscribe进行操作,然后通过布尔值检查Boolean那里,filter等。

答案 1 :(得分:0)

akarnokd的RxJava2Extensions额外项目有一个filterAsync变换器(与compose一起使用)就可以使用任意Publisher<Boolean>;)

答案 2 :(得分:0)

我想出了解决方案,但没有传递带有布尔值的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 -> ...)