One Off the Slack: MutableState or StateFlow?

Lilly asked:

I’m wondering, what are the differences between StateFlow and MutableState 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 a Flow somewhere you can use snapshotFlow {} 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 a State<T> anyway, so using mutableStateOf 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!