One Off the Slack: MutableState or StateFlow?
Lilly asked:
I’m wondering, what are the differences between
StateFlow
andMutableState
in viewmodel/presenter layer? Is there a rule of thumb when to use one over the other, are there any drawbacks to use the one or the other? It seems to me both work the same way
Google’s Adam Powell replied:
imo use
[Mutable]State
for things consumed by your UI. If you need aFlow
somewhere you can usesnapshotFlow {}
to get one
Snapshot state is generally easier to work with via the property delegates and works transitively across the call stack without having to assemble an operator chain. All snapshot state objects are guaranteed to be transactionally consistent with one another during composition, which is not a guarantee with separate StateFlows; in those use cases if you want to ensure that same consistency you would have to merge them into a single stream.
And finally,
.collectAsState
simply collects the flow and copies it into aState<T>
anyway, so usingmutableStateOf
directly instead saves some steps.
Jason Ankers countered:
I’d argue combining flows is a positive. If a screen is composed of multiple independent remote data sources, doing something like this feels nice:
val uiState = combine(source1, source2, source3) {
emit(UiState.Loaded)
}.onStart {
emit(UiState.Loading)
}.catch {
emit(UiState.Error)
}
Adam replied:
if you’ve got cold flows, sure, but since we were talking about [Mutable]StateFlows above that don’t complete or emit errors, and source1-3 must be multicast/hot to communicate the actual values somewhere else, the (observable!) equivalent using snapshot state might look something like:
val isLoaded: Boolean
get() = source1 != null && source2 != null && source3 != null
or replace the null with whatever other initial-value sentinel you might be using. No special API needed, just plain Kotlin.
Finally, Efeturi Money asked if [Mutable]State
was usable across platforms, and Adam responded:
yes, it’s supported on any platform compose targets
So, you can use it on Compose for Desktop and (presumably) Compose for Web as well as on Android.
Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!