如何使用Rx Java达到此要求

时间:2018-12-13 12:23:24

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

我的State(Enum)包含(良好,非关键,关键)值

所以要求是:

  1. 状态变为非紧急状态时应触发。
  2. 状态变为紧急状态时应触发。
  3. 状态保持在临界状态15秒后应触发。

输入:

publishSubject.onNext("Good")
publishSubject.onNext("Critcal") 
publishSubject.onNext("Critcal") 
publishSubject.onNext("NonCritical")  
publishSubject.onNext("Critacal") 
publishSubject.onNext("Critical") 
publishSubject.onNext("Good")
and so on...

请参阅代码结构以供参考:

    var publishSubject = PublishSubject.create<State>()
    publishSubject.onNext(stateObject)


    publishSubject
            /* Business Logic Required Here ?? */
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                AppLogger.printLog("Trigger Success --> ")
            }

请帮助, 预先感谢,

2 个答案:

答案 0 :(得分:2)

您可以使用distinctUntilChanged()来抑制不会更改状态的事件。使用filter()过滤掉正常事件。

状态更改时,使用switchMap()运算符创建新的订阅。当状态为“紧急”时,请使用interval()运算符等待15秒。如果状态在这15秒钟内发生变化,switchMap()将退订并重新订阅新的可观察对象。

publishSubject
  .distinctUntilChanged()
  .subscribeOn(Schedulers.computation())
  .observeOn(AndroidSchedulers.mainThread())
  .filter( state -> state != State.Normal )
  .switchMap( state -> {
                   if (state == State.Critical) {
                     return Observable.interval(0, 15, TimeUnit.SECONDS) // Note 1
                        .map(v -> State.Critical); // Note 2
                   }
                   return Observable.just( State.Noncritical );
                 })
  .subscribe( ... );
  1. interval()的初始值为0,使其立即发出一个值。在15秒之后,将发出下一个值,依此类推。
  2. map()运算符将Long发出的interval()变成

答案 1 :(得分:0)

您的需求的前两个部分应该合并为一个。您要求在NonCriticalCritical事件上触发链,因此,应该Good事件触发链。同样,仅在状态不同于上一个事件时才需要触发事件。对于这两个.filter事件应该足够了:

var lastKnownState: State = null

publishSubject
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .filter(this::checkStateDiffers)       // Check we have a new state
        .filter { state -> state != State.Good }        // Check event is good
        .subscribe {
            AppLogger.printLog("Trigger Success --> ")
        }

...

private fun checkStateDiffers(val state: State): Boolean {
     val isDifferent = state != lastKnownState
     if (isDifferent) lastKnownState = state       // Update known state if changed
     return isDifferent
}

超时要求有点棘手。当在一段时间内未收到任何新消息时,RxJava的timeout()运算符提供发出错误的选项。但是,我假设即使在收到超时后,您仍要继续监听事件。同样,如果我们仅发送另一个Critical事件,它将被第一个filter丢弃。因此,在这种情况下,我建议使用第二个一次性的,可以用来监听此超时情况。

Disposable timeoutDisp = publishSubject
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .timeout(15, TimeUnit.SECONDS)
        .onErrorResumeNext(State.Timeout)
        .filter { state -> state == State.Timeout }
        .filter { state -> lastKnownState == State.Critical }
        .subscribe {
            AppLogger.printLog("Timeout Success --> ")
        }

还要调整checkStateDiffers(),以使其不在第一条链中保存此Timeout状态。

private fun checkStateDiffers(val state: State): Boolean {
     if (state == State.Timeout) return true

     var isDifferent = state != lastKnownState
     if (isDifferent) lastKnownState = state       // Update known state if changed
     return isDifferent
}