RxJava条件FlatMap清理方式

时间:2019-04-11 09:25:41

标签: rx-java rx-java2 code-cleanup

我正在寻找一种更干净的方法来创建条件flatMap(),我已经读过this,但是在将其应用于我的代码时遇到了麻烦:

// 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()函数。

2 个答案:

答案 0 :(得分:1)

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

我假设您想知道这只猫何时需要喂食。因此,我认为可观察的会更合适:

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)

我已经对该代码进行了单元测试(不是猫,猫被吃掉了,猫没有被吃掉),所以我对此答案很有信心。

答案 1 :(得分:1)

我已将第二个if提取到扩展函数中

// 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") {
                isCatEat.flatMapIfTrue { feedCat }
            } else {
                Single.fromCallable { false }
            }
        }

位置:

fun Single<Boolean>.flatMapIfTrue(mapper: (Boolean) -> Single<Boolean>): Single<Boolean> =
        this.flatMapIf({ it }, mapper)

fun Single<Boolean>.flatMapIfFalse(mapper: (Boolean) -> Single<Boolean>): Single<Boolean> =
        this.flatMapIf({ !it }, mapper)

fun <T> Single<T>.flatMapIf(conditions: (T) -> Boolean, mapper: (T) -> Single<T>): Single<T> =
        this.flatMap {
            if (conditions(it)) mapper(it)
            else Single.just(it)
        }

我提供了3个fun,因此您可以在其他地方重复使用