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