Reputation: 2126
I recently started using Flows in Android. I read that Flows are cold StateFlows are hot, then why should we prefer using StateFlows for Android over Flows? Won't it be better to use Flows as they will stop the producer when the app goes to the background? Is there a scenario in Android development where Flows should be used over Stateflow?
Upvotes: 20
Views: 15533
Reputation: 254
that actually bothers me a while before.
So I think best way to compare these two is that, StateFlow holds a value, but Flow does not. For example:
val myStateFlow = MutableStateFlow("x")
myStateFlow.value = "y"
however, for Flow, it doesn't hold a value, instead they do something
val myFlow = flow {
repeat(5) { emit(it) }
}
Upvotes: 10
Reputation: 4229
Won't it be better to use Flows as they will stop the producer when the app goes to the background?
This is not true. Flow
on its own will not stop emitting when the app is in the background. In fact, the Flow
interface belongs to Kotlin's coroutines and knows nothing of Android.
Simply put, a Flow
will give you a new value every time a new value is emitted. A StateFlow
, in addition to what a Flow
is, it always holds a value. This makes them ideal for representing state (as the name suggests).
Is there a scenario in Android development where Flows should be used over Stateflow?
You can use Flow when you do not need to maintain a value and care for the emittions. An example would be a button press or user event. A StateFlow
is useful for representing state (such as in your ViewModels)
Upvotes: 13
Reputation: 27246
The Advantage of the StateFlow
over a regular Flow
is that the former will stop wasting resources if the State is not the desired one.
If you look at the official StateFlow documentation you'll notice in the example the key part of this, and I quote:
// Trigger the flow and start listening for values.
// Note that this happens when lifecycle is STARTED and stops
// collecting when the lifecycle is STOPPED
This last bit is important. A Hot
flow that will be collecting values so as long as the scope in which it was started is Started, and will stop when stopped. This is not what a normal Flow/Livedata would do thus wasting potential resources keeping a series of components working while, for example, the UI is stopped.
It's important to understand that LiveData
and StateFlow
are similar with two important distinctions (related with the above, and explained in the linked documentation):
StateFlow
requires an initial state to be passed in to the constructor, while LiveData
does not.
LiveData.observe()
automatically unregisters the consumer when the view goes to the STOPPED state, whereas collecting from a StateFlow or any other flow does not stop collecting automatically. To achieve the same behavior, you need to collect the flow from a Lifecycle.repeatOnLifecycle
block.
In other words, you could say that StateFlow
is a potentially more efficient LiveData that gives you the ability to say: If the state is XYZ, then stop collecting and using resources because I have my reasons (e.g.: my UI is gone, so i don't need to listen to stuff I cannot process).
Upvotes: 21
Reputation: 1220
Firstly, I would like to mention that StateFlow is already implemented Flow interface if you check implementation of source code. StateFlow is observable data holder which gives always last value of pipeline. It makes sense to compare it with LiveData actually. You already right that it is hot unlike flow is cold. If you want to stop producer when the app goes the background, Channel API is better for this purpose. If we come what is the Flow purpose, you can handle multiple suspend methods via Flow API. For example : You can observe two suspend function continuously.
Upvotes: 1