https://kotlinlang.org logo
#mvikotlin
Title
# mvikotlin
n

Nacho Ruiz Martin

11/18/2023, 7:15 AM
Hey @Arkadii Ivanov, WDYT of adding a built-in way of mapping states out of the store when using
stateFlow
extension? I’ve found that if you map it with:
Copy code
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.
I’ve copied the source of the
stateFlow
extension and modified it in my app. It looks like:
Copy code
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()
        }
    }
}
Problem:
stateFlow
is no longer a variable, but a function.
a

Arkadii Ivanov

11/18/2023, 10:09 AM
WDYT of adding a built-in way of mapping states out of the store when using
stateFlow
extension?
Technically it's possible, but's not as easy as it may look like. I.e. ideally the
value
property should be cached to avoid calling the mapper every time.
you fall into the everlasting problem of textfield states
You 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.
n

Nacho Ruiz Martin

11/18/2023, 12:18 PM
Oh, didn't know you could also stateIn Dispatchers.Main! I'll try that one. Many thanks.
a

Arkadii Ivanov

11/18/2023, 12:19 PM
I don't think you can, stateIn needs a CoroutineScope. But you can create the scope with Dispatchers.Main.immediate.
n

Nacho Ruiz Martin

11/18/2023, 12:19 PM
Ah, ok that makes even more sense 👍