何时不使用RxJava的Observable?

时间:2016-09-19 01:02:07

标签: java android rx-java kotlin rx-android

例如,我在我的应用程序中有一个简单的管理器,我试图保留所有内容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 && isLockTimerExpired() }
                .doOnNext { logger.debug("shouldLock: $it") }
                .compose(rxHelper.applySchedulers())
    }

    private fun isLockTimerExpired(): Boolean {
        if(lastUnlockTime == null) return true
        val timerExpiredMoment = lastUnlockTime!!.plusSeconds(30)
        val now = LocalDateTime.now().isAfter(timerExpiredMoment)
        val isExpired = LocalDateTime.now().isAfter(timerExpiredMoment)
        logger.debug("timerExpiredMoment: $timerExpiredMoment / now: $now; isExpired: $isExpired")
        return isExpired
    }

    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())
    }

}

这是一个简单的课程,可以计算时间,并在必须锁定我的申请时从true发出shouldLock()

我有如何使用它:

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
                    }
                }
            }))
}
看起来很难看,不是吗? :)

我找不到合适的运算符来将空的Observable(appLockManager.setLocked())与securityManager.anyPassword() wwitch返回Observable组合,并发出一个项目。

这让我相信我不应该将RxJava用于像appLockManager.setLocked()这样的方法。

我应该在这里使用Observable吗?特别适用于setLocked() / setUnlocked() / resetLockTimer()只更新AppLockManager并且根本不返回任何数据的方法

2 个答案:

答案 0 :(得分:2)

使用嵌套订阅会导致代码异味。要在完成另一个Observable之后使用另一个concat,您可以.flatMap { if(it == true) Observable.just(it) else Observable.never() } 可观察数据。

您的代码可以更简单。例如,而不是使用它:

filter

您可以改为使用filter

因此,删除嵌套订阅+ 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 } }) } 将导致此代码:

list

答案 1 :(得分:0)

@dwursteisen提供的另一种解决方案是使用Completable。根据{{​​3}},它刚刚成为@Beta

改进了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
                }
            })
}

setLock()返回Completable的位置:

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

此外,Observable中的shoudlLock()可以替换为Single(发出一个项目的Observable)。