¿Cuándo no usar el Observable de RxJava?

Por ejemplo, tengo un Administrador simple en mi aplicación en el que trato de mantener todo reactive :

 class AppLockManager { private val logger = LoggerFactory.getLogger(javaClass) private val rxHelper: RxHelper private val securityManager: DiarySecurityManager private var locked = false private var lastUnlockTime: LocalDateTime? = null constructor(rxHelper: RxHelper, securityManager: DiarySecurityManager) { this.rxHelper = rxHelper this.securityManager = securityManager } fun shouldLock(): Observable<Boolean> { return securityManager.isSecutiryEnabled() .doOnNext { logger.debug("isSecurityEnabled: $it") } .map { it && !locked && isLockTimerExpinetworking() } .doOnNext { logger.debug("shouldLock: $it") } .compose(rxHelper.applySchedulers()) } private fun isLockTimerExpinetworking(): Boolean { if(lastUnlockTime == null) return true val timerExpinetworkingMoment = lastUnlockTime!!.plusSeconds(30) val now = LocalDateTime.now().isAfter(timerExpinetworkingMoment) val isExpinetworking = LocalDateTime.now().isAfter(timerExpinetworkingMoment) logger.debug("timerExpinetworkingMoment: $timerExpinetworkingMoment / now: $now; isExpinetworking: $isExpinetworking") return isExpinetworking } fun setLocked(): Observable<Void> { return Observable.create<Void> { this.locked = true it.onCompleted() }.compose(rxHelper.applySchedulers()) } fun setUnlocked(): Observable<Void> { return Observable.create<Void> { this.locked = false lastUnlockTime = LocalDateTime.now() }.compose(rxHelper.applySchedulers()) } fun resetLockTimer(): Observable<Void> { return Observable.create<Void> { lastUnlockTime = LocalDateTime.now() }.compose(rxHelper.applySchedulers()) } } 

Es una class simple que count el time y emite true desde shouldLock() cuando mi aplicación debe estar bloqueada.

Así es como lo uso:

 fun lockAppIfNeeded() { appLockManager.shouldLock() .doOnNext { logger.debug("shouldLock: $it") } .flatMap { if(it == true) Observable.just(it) else Observable.never() } // flow down only if it == true .flatMap { appLockManager.setLocked() } // then lock .subscribe(sub({}, Throwable::printStackTrace, { // use onComplete as source Observable is empty securityManager.anyPassword().subscribe { if (it) { view.navigateToAskPassword() // anyPassword is true } else { view.navigateToFirstPasswordSetup() // anyPassword is false } } })) } 

Se ve feo, ¿no? 🙂

Simplemente no puedo encontrar el operador correcto para combinar Observable vacío ( appLockManager.setLocked() ) con securityManager.anyPassword() wwitch return Observable que emite un elemento.

Esto me ha llevado a creer que no debería usar RxJava para methods como appLockManager.setLocked() .

¿Debo usar Observables aquí? Especialmente para los setLocked() / setUnlocked() / resetLockTimer() que solo actualizan AppLockManager y no devuelve ningún dato.

Usar una suscripción anidada es un mal olor a código. Para utilizar otro Observable después de completar otro, puede concat Observables.

Tu código puede ser más simple. Por ejemplo, en lugar de usar esto:

 .flatMap { if(it == true) Observable.just(it) else Observable.never() } 

puedes usar filter lugar.

Así que eliminar el filter + suscripción nested conducirá a este código:

 fun lockAppIfNeeded() { appLockManager.shouldLock() .doOnNext { logger.debug("shouldLock: $it") } .filter { it } // flow down only if it == true .flatMap { appLockManager.setLocked() } // then lock .ignoreElements() // throw away appLockManager items .concatWith(securityManager.anyPassword()) .subscribe { if (it) { view.navigateToAskPassword() // anyPassword is true } else { view.navigateToFirstPasswordSetup() // anyPassword is false } }) } 

Una solución alternativa a la presentada por @dwursteisen será usar Completable . De acuerdo con el logging de cambios , simplemente se convirtió en @Beta .

Hay un lockAppIfNeeded() mejorado lockAppIfNeeded() :

 fun lockAppIfNeeded() { appLockManager.shouldLock() .doOnNext { logger.debug("shouldLock: $it") } .filter { it } // flow down only if it == true .toCompletable() .concatWith(appLockManager.setLocked()) // then lock .andThen(securityManager.anyPassword()) .subscribe(sub { if (it) { view.navigateToAskPassword() // anyPassword is true } else { view.navigateToFirstPasswordSetup() // anyPassword is false } }) } 

Donde setLock() devuelve Completable :

 fun setLocked(): Completable { return Completable.fromAction { this.locked = true } .compose(rxHelper.applySchedulersToCompletable()) } 

Además, Observable en shoudlLock() se puede replace por Single ( Observable que emite un elemento).

  • Combina Rx Singles en Observables recursivamente
  • RxJava: anular la suscripción asincrónica observable desde dentro de otra producción asincrónica
  • Uso del map RXJava en Kotlin?
  • Kotlin RxJava Bug Nullable
  • Cambiar Observable desde AutoCompleteTextView a EditText
  • ¿Por qué obtengo una android.os.TransactionTooLargeException en mi aplicación de Android escrita en Kotlin / rxJava cuando salgo de la aplicación? (onExit / onPause)?
  • Comportamiento de RxJava Schedulers.immediate () mientras testings unitarias
  • ¿Cómo se coordina una list de ejecuciones Completables con RxJava?
  • Kotlin - ¿Cómo crear una function de alias de RxJava flatmap ()?
  • ¿Por qué mi configuration de RxJava está bloqueando mi subprocess de interfaz de usuario? Trabajar con la callback BluetoothAdapter.startLeScan
  • Cómo get el valor del ObservableField en android