RxJava Условный очиститель FlatMap - PullRequest
0 голосов
/ 11 апреля 2019

Я ищу более чистый способ создания условного 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 ]

1 голос
/ 11 апреля 2019

Я извлек второе 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 с, чтобы вы могли использовать его в других местах

1 голос
/ 11 апреля 2019

Вы можете использовать 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)

Я тестировал этот код (не кошка, кошка съела и кошка не съела), поэтому я довольно уверен в этом ответе.

...