首页 > 解决方案 > RxJava 条件 FlatMap 更清洁的方式

问题描述

我正在寻找一种更简洁的方法来创建条件flatMap(),我已经阅读了这个,但我无法将它应用到我的代码中:

// given variables for the sake of simplicity
val stringSingle = Single.just("dog")
val isCatEat = Single.just(true)
val feedCat = Single.just(true)

// example
stringSingle
   .flatMap { string -> 
      if (string == "cat") {
         return@flatMap isCatEat()
             .flatMap { isCatEat ->
                if (isCatEat) { // if cat already ate, proceed immediately
                    Single.fromCallable { true }
                } else { // if not, feed cat
                   feedCat()
                }
             }
      } else {
         Single.fromCallable { false }
      }
   }

正如你所看到的(好吧,代码非常难看,嵌套啊),feedCat()如果猫已经吃过,我想通过首先检查它来避免调用。我无法应用compose()功能,因为我无法重现我的状况。

标签: rx-javarx-java2code-cleanup

解决方案


您可以使用filter, 仅在满足谓词时才会发出。

我假设你想知道这只猫什么时候需要喂食。因此,我认为 observable 会更合适:

private val hasCatEaten = Single.just(true)

fun feedCat(animal: String): Observable<Unit> =
        Observable.just(animal)
                .filter { it == "cat" }
                .flatMapSingle { hasCatEaten }
                .filter { !it }
                .map { Unit }

fun observeFeedCat() {
    feedCat("cat")
            .subscribeOn(schedulers.ioScheduler())
            .observeOn(schedulers.mainScheduler())
            .subscribeBy(onNext = { // Called when cat needs to be fed })
            .addTo(disposables)
}

更新

这是一个更好的解决方案,它可以处理两种情况:

    fun shouldFeed(animal: String): Single<Boolean> =
        Single.fromCallable { animal }
                .filter { it == "cat" }
                .flatMap { Maybe.fromCallable { !hasEaten } }
                .toSingle(false)

我对这段代码进行了单元测试(不是猫,猫吃过猫没吃过),所以我对这个答案非常有信心。


推荐阅读