Nacho Ruiz Martin
11/18/2023, 7:15 AMstateFlow
extension?
I’ve found that if you map it with:
store.stateFlow.map(::mapper).stateIn(scope, SharingStarted.Eagerly, store.state.mapper())
you fall into the everlasting problem of textfield states.
I’ve been thinking of adding an optional mapping function inside stateFlow
. This would help users of MviKotlin
+ Decompose
that want to use Coroutines
all the way down.stateFlow
extension and modified it in my app. It looks like:
fun <State : Any, Model : Any> Store<*, State, *>.stateFlow(mapper: State.() -> Model): StateFlow<Model> =
StoreStateFlow(store = this, mapper)
private class StoreStateFlow<State : Any, Model : Any>(
private val store: Store<*, State, *>,
private val mapper: State.() -> Model,
) : StateFlow<Model> {
override val value: Model get() = store.state.mapper()
override val replayCache: List<Model> get() = listOf(store.state.mapper())
override suspend fun collect(collector: FlowCollector<Model>): Nothing {
val flow = MutableStateFlow(store.state.mapper())
val disposable = store.states(observer { flow.value = it.mapper() })
try {
flow.collect(collector)
} finally {
disposable.dispose()
}
}
}
stateFlow
is no longer a variable, but a function.Arkadii Ivanov
11/18/2023, 10:09 AMWDYT of adding a built-in way of mapping states out of the store when usingTechnically it's possible, but's not as easy as it may look like. I.e. ideally theextension?stateFlow
value
property should be cached to avoid calling the mapper every time.
you fall into the everlasting problem of textfield statesYou should use
Dispatchers.Main.immediate
there as well. E.g. the scope you are passing into stateIn
function should be created with Main.immediate
dispatcher. And also use Main.immediate
when you collect the flow. Then it should work fine.Nacho Ruiz Martin
11/18/2023, 12:18 PMArkadii Ivanov
11/18/2023, 12:19 PMNacho Ruiz Martin
11/18/2023, 12:19 PM