Hi there. Need an advice. Inside a
ViewModel
, I had a basic MVI-inspired state machine implemented in the following way:
/**
* State machine for this view model consisting of [Interactor], [State], [Event] and [Reducer]
* It reduces [Event] to the immutable [State] by applying [Reducer] fuction.
* This [State] then will be rendered.
*/
class Interactor(
private val scope: CoroutineScope,
private val reducer: Reducer = Reducer(),
private val channel: Channel<Event> = Channel(),
private val events: Flow<Event> = channel.consumeAsFlow()
) {
fun onEvent(event: Event) = scope.launch { channel.send(event) }
fun state(): Flow<State> = events.scan(State.init(), reducer.function)
}
interface StateReducer<STATE, EVENT> {
val function: suspend (STATE, EVENT) -> STATE
suspend fun reduce(state: STATE, event: EVENT): STATE
}
But then I was unable to get current state, I could only observe it as a
Flow<State>
, so I re-implemented it in the following manner:
class Interactor(
private val scope: CoroutineScope,
private val reducer: Reducer = Reducer(),
private val channel: Channel<Event> = Channel(),
private val events: Flow<Event> = channel.consumeAsFlow()
) {
val state = ConflatedBroadcastChannel<State>()
init {
scope.launch {
events.scan(State.init(), reducer.function).collect { state.send(it) }
}
}
fun onEvent(event: Event) = scope.launch { channel.send(event) }
fun state(): Flow<State> = state.asFlow()
}
I guess it could be improved. Are there any inherent problems to this implementation? Thanks a lot, in advance đź’Ą.