StateFlow and SharedFlow in kotlin

zouhair zghiba
4 min readMar 10, 2023

--

In Kotlin, there are two types of flows: Cold Flow and Hot Flow.
Hot Flows are those that start emitting values even if there are no collectors attached to them.
Two examples of Hot Flows in Kotlin are StateFlow and SharedFlow.

In this article, we will explore these two flows in detail and understand their use cases.

StateFlow :

StateFlow is a Hot Flow that needs an initial value and emits it as soon as a collector starts collecting. It only emits the last known value, and it does not emit consecutive repeated values. In other words, it only emits values that are distinct from the previous item. StateFlow is similar to LiveData in terms of functionality, except for the Lifecycle awareness of the Android component. We should use the repeatOnLifecycle scope with StateFlow to add Lifecycle awareness to it, making it exactly like LiveData.

To understand this better, let’s consider an example where we have a StateFlow variable as follows:

val stateFlow = MutableStateFlow("Hello")

// If we start collecting on it, as shown below:
stateFlow.collect {
println(it)
}

// As soon as we start collecting, we will get the initial value, which is
// "Hello". If we set the values as follows:
stateFlow.value = "World"
stateFlow.value = "World"
stateFlow.value = "Hello"
stateFlow.value = "medium"

// We will get the following output:
// Notice that we only get "World" once, not twice, as StateFlow does not emit
// consecutive repeated values.

Hello
World
Hello
medium

If we add a new collector, we will get the last value emitted:

stateFlow.collect {
println(it)
}

// We will get:
medium

in real life StateFlow could be a traffic light. The traffic light has three states: red, yellow, and green. The state can change over time based on external factors such as the time of day, the number of cars on the road, and whether there are any accidents or construction. StateFlow can be used to represent the current state of the traffic light, and it can be updated over time as the state changes.

val trafficLightState = MutableStateFlow("red")

fun changeTrafficLightState(newState: String) {
trafficLightState.value = newState
}

trafficLightState.collect {
Log.d("TrafficLightState", it)
}

SharedFlow :

SharedFlow is also a Hot Flow, but it does not need an initial value and, therefore, does not emit any value by default. It emits all the values and does not care if the value is distinct from the previous item.
In other words, it emits consecutive repeated values. SharedFlow is not similar to LiveData.

To understand this better, let’s consider an example where we have a SharedFlow variable as follows:

val sharedFlow = MutableSharedFlow("Hello")

// If we start collecting on it, as shown below:
sharedFlow.collect {
println(it)
}

// As soon as we start collecting, we will not get anything as it does not take
// an initial value. If we emit values as follows:

sharedFlow.value = "Hello"
sharedFlow.value = "World"
sharedFlow.value = "World"
sharedFlow.value = "Hello"
sharedFlow.value = "medium"

// We will get the following output:
// Notice that we get "World" twice, as SharedFlow emits consecutive
// repeated values. If we add a new collector, we will not get anything,
// as SharedFlow does not store the last value.

Hello
World
World
Hello
medium

In real life SharedFlow could be a radio station. The radio station broadcasts music and news to its listeners, and the listeners can tune in to listen to the broadcast. The radio station is emitting multiple values over time (music and news), and it can be shared between multiple listeners.

Here is an example of how SharedFlow can be used in Kotlin:

val radioStation = MutableSharedFlow<String>()

fun broadcastMessage(message: String) {
radioStation.tryEmit(message)
}

radioStation.collect {
Log.d("RadioStation", it)
}

StateFlow vs SharedFlow :

Let’s now compare the differences between StateFlow and SharedFlow:

StateFlow:

  • StateFlow is a hot flow that emits the latest state value and all subsequent updates to its collectors.
  • It is backed by a mutable state variable that can be updated using the value property.
  • When a collector starts to collect from a StateFlow, it will immediately receive the latest value emitted by the flow and then all subsequent updates as they occur.
  • StateFlow is suitable for representing a single source of truth in an application, such as the current user authentication state or a shopping cart content.
  • StateFlow is not thread-safe, and should be accessed only from a single thread.
  • StateFlow can be used to expose state updates from ViewModel to the UI layer and propagate user interactions from UI layer to ViewModel.

SharedFlow:

  • SharedFlow is a hot flow that emits values to its collectors only after they start to collect from it.
  • It is backed by a buffer that stores emitted values until they are collected by all collectors.
  • When a collector starts to collect from a SharedFlow, it will receive all buffered values and then all subsequent updates as they occur.
  • SharedFlow is suitable for representing events, such as user actions or network responses, that may be missed by some collectors if they occur before they start collecting from the flow.
  • SharedFlow is thread-safe and can be accessed from multiple threads.
  • SharedFlow can be used to publish events to multiple subscribers, such as sending push notifications to multiple devices or updating a database cache.

--

--

zouhair zghiba

A software engineer focused on building Android mobile products, its tools, architecture and devOps. always in experimenting and learning style