What are the differences between SharedFlow and StateFlow?
And how to use these in MVI architecture? is it better to use simple Flow or these as states and events?
Flow is cold!, means it emits data only when it is collected. Also Flow cannot hold data, take it as a pipe in which water is flowing , data in flow only flows , not stored(no .value function).
Unlike Flow, StateFlow and SharedFlow are hot streams means they emit data even when there is no collector. Also if there are multiple collectors, a new Flow will be run for each collector, completely independent from each other. SharedFlow and StateFlow are Flows that allow for sharing itself between multiple collectors, so that only one flow is effectively run for all of the simultaneous collectors. If you define a SharedFlow that accesses databases and it is collected by multiple collectors, the database access will only run once, and the resulting data will be shared to all collectors.
What are the differences between SharedFlow and StateFlow?
StateFlow
Stateflow takes an initial value through constructor and emits it immediately when someone starts collecting. It gives the latest value to a subscriber even if multiple values are emitted from the flow in quick succession. So if you are collecting in a collector like so:
val stateFlow = MutableStateFlow(0)
val collector = launch {
val value = stateFlow.value
println("Received: $value")
}
Say in some other part of the code the stateFlow gets the value 1, 2, 3 in rapid succession the println statement will print 3 when the collector runs if between the time the corouritine took to ran and reading of the value
, all the values were already posted.
Stateflow is almost identical to LiveData. LiveData automatically unregisters the consumer when the view goes to the STOPPED state. When collecting a StateFlow this is not handled automatically , you can use repeatOnLifeCyCle scope if you want to unregister the consumer on STOPPED state.
SharedFlow
StateFlow only emits last known value , whereas SharedFlow can configure how many previous values to be emitted. More precisely it has the capability to hold in the emission channel/buffer values until you are ready to consume them so you might get all of them. Lets take the simplest case when replay = 0, this highlights the most subtle difference: new subscribers don't get any values emitted to previous subscribers.
val sharedFlow = MutableSharedFlow<Int>(replay = 0)
val collector = launch {
sharedFlow.collect { value ->
println("Received: $value")
}
}
With the same example 1,2,3 in rapid succession, you might print all three numbers. This is because shared flow can suspend emissions(done explicitly using emit calls) when the consumer is not ready.
If you want emitting and collecting repeated values , use sharedflow.
Summary
In summary, use StateFlow when you need to manage and share a single state with multiple collectors. Instead, use SharedFlow when you need to share a stream of events among collectors without holding any state.