Kotlin 用RxJava构建MVI循环:如何用scan()替换BehaviorSubject

Kotlin 用RxJava构建MVI循环:如何用scan()替换BehaviorSubject,kotlin,rx-java2,behaviorsubject,Kotlin,Rx Java2,Behaviorsubject,我试图找出一种方法来消除可变状态,从而消除可能的竞争条件。但我似乎不知道如何在使用“扫描”的同时,以某种方式“交织”两个观察值 希望通过展示更多的代码,我能给你一个想法: private val stateRelay: BehaviorRelay<State> = BehaviorRelay.createDefault(initialState ?: DEFAULT_STATE) // maybe this should be `Observable.startWith()` som

我试图找出一种方法来消除可变状态,从而消除可能的竞争条件。但我似乎不知道如何在使用“扫描”的同时,以某种方式“交织”两个观察值

希望通过展示更多的代码,我能给你一个想法:

private val stateRelay: BehaviorRelay<State> = BehaviorRelay.createDefault(initialState ?: DEFAULT_STATE) // maybe this should be `Observable.startWith()` somehow?

fun bindIntents(intents: Observable<Actions>, stateRenderer: StateRenderer) {
    compositeDisposable += intents.concatMap { action ->
        when (action) {
            is Actions.Increment -> {
                Observable.create<Change> { emitter -> 
                   // emit things
                }
            }
            is Actions.Decrement -> {
                Observable.create<Change> { emitter -> 
                   // emit things
                }
            }
        }
    }.map { change ->
        reducer(stateRelay.value, change) // TODO: figure out how to use scan() here, instead of stateRelay.value! :(
    }.subscribeBy { newState ->
        stateRelay.accept(newState) // there is a chance that the relay shouldn't be here if scan is used
    }

    compositeDisposable += 
        stateRelay // TODO: figure out how to use scan() instead of a relay!
            .distinctUntilChanged()
            .subscribeBy { state ->
                stateRenderer(state)
            }
}

fun unbindIntents() {
    compositeDisposable.clear()
}


我如何包装
intents.concatMap.map
,作为
Observable.scan()
(可能带有
startWith()
replay(1)
)的一部分,以消除我对行为主体的使用?

我将详细阐述我上面的评论。 这是一个简单的代码重写,以实现您的要求

fun bindIntents(intents: Observable<Actions>, stateRenderer: StateRenderer) {
    val stateObservable = intents.concatMap { action ->
        when (action) {
            is Actions.Increment -> {
                Observable.create<Change> { emitter ->
                // emit things
                }
            }
            is Actions.Decrement -> {
                Observable.create<Change> { emitter ->
                    // emit things
                }
            }
        }
    }.scan(initialState, { currentState, change -> reducer(currentState, change)})

    compositeDisposable +=
        stateObservable
                .distinctUntilChanged()
                .subscribeBy { state ->
                    stateRenderer(state)
                }
}

我看到了与之类似的部分,但它是RxJS,不完全适用。
intents.concatMap.map
的映射部分应替换为
.scan(initialState,{currentState,change->reducer(currentState,change)
并删除那里的subscribeBy。该块现在返回一个可观察的,而不是一次性的。将该可观察的放在第二位的stateRelay的位置,基本上就完成了。对不起,我当然是说,
.scan
位返回一个
可观察的
@Liminal。我一直在做一些调整,但我看不出来为了弄清楚我应该调用什么
observatable.scan()
。我已经用我自那以后所做的更改编辑了这个问题-例如,正如你提到的,合并了两个观察值。通过一些研究,显然我需要以某种方式应用RxFeedback所做的相同事情:嗯。所以你真的只需要交换
映射(reducer){getValue()
扫描(initialState,reducer)
一起工作。我也非常接近……谢谢!:DI还添加了一个
重播(1)。最后自动连接(0)
,看起来是正确的。
fun bindIntents(intents: Observable<Actions>, stateRenderer: StateRenderer) {
    val stateObservable = intents.concatMap { action ->
        when (action) {
            is Actions.Increment -> {
                Observable.create<Change> { emitter ->
                // emit things
                }
            }
            is Actions.Decrement -> {
                Observable.create<Change> { emitter ->
                    // emit things
                }
            }
        }
    }.scan(initialState, { currentState, change -> reducer(currentState, change)})

    compositeDisposable +=
        stateObservable
                .distinctUntilChanged()
                .subscribeBy { state ->
                    stateRenderer(state)
                }
}
fun bindIntents(intents: Observable<Actions>, stateRenderer: StateRenderer) {
    compositeDisposable +=
            intents.concatMap { action ->
                when (action) {
                    is Actions.Increment -> {
                        Observable.create<Change> { emitter ->
                            // emit things
                        }
                    }
                    is Actions.Decrement -> {
                        Observable.create<Change> { emitter ->
                            // emit things
                        }
                    }
                }
            }.scan(initialState, this::reducer)
                    .distinctUntilChanged()
                    .subscribeBy { state ->
                        stateRenderer(state)
                    }
}