StateFlow and SharedFlow: the new hot stream APIs in town
Tags: android, kotlin
Published: 2021-02-07 01:05:15

---
title: StateFlow and SharedFlow: the new hot stream APIs in town
published: true
date: 2021-02-07 00:52:27 UTC
tags: Android,Kotlin
canonical_url: https://www.rockandnull.com/stateflow-kotlin/
---

 ![StateFlow and SharedFlow: the new hot stream APIs in town](https://images.unsplash.com/photo-1560950666-0561e630a681?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMTc3M3wwfDF8c2VhcmNofDIwNHx8c3RyZWFtfGVufDB8fHw&ixlib=rb-1.2.1&q=80&w=2000)

There's been quite a hype around the (kind of) newly introduced `StateFlow` and `SharedFlow` in Kotlin/Android community.

These are the new Kotlin `Flow` APIs. But these are not for ["cold" streams](https://dev.to/mavris/into-the-flow-kotlin-cold-streams-primer-128i) (i.e. data are generated and emitted when there's a subscriber). These are for "hot" streams (i.e. data are emitted anyway and any active subscribers will receive them).

If this reminds you of `LiveData` it's because this is another "hot" stream implementation. The data are emitted anyway from the ViewModel, and any subscriber in the View will get those values.

So should we replace `LiveData` with `StateFlow`? Is it that simple? And does it worth it?

## StateFlow

The API for `StateFlow` is almost identical to `LiveData`. You have a `MutableStateFlow` that "drives" the `StateFlow` (similar to how a `MutableLiveData` "drives" a `LiveData`).

```
class MyViewModel(private val repository: Repository) : ViewModel() {

    private val userNameFlow = MutableStateFlow("") // 1.
    
    val userName: StateFlow<String> = userNameFlow

    init {
        viewModelScope.launch {
            userNameFlow.value = repository.fetchUserName()
        }
    }
}
```
<figcaption>ViewModel</figcaption>

```
class MyActivity : AppCompatActivity() {
    private val viewModel = getViewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        lifecycleScope.launchWhenStarted { // 2.
            viewModel.userName.collect { userName ->
                userNameLabel.text = userName
            }
        }
    }
}
```
<figcaption>View</figcaption>
1. In contrast with `LiveData`, `StateFlow` always needs an initial value.
2. This runs when the lifecycle is at least in the `STARTED` state.

Note that (2) might be an issue. `LiveData` automatically unregisters the consumer when the view goes to the STOPPED state. When collecting a `StateFlow` this is not handled automatically.

To address this issue you can either start and stop collecting values from `StateFlow` manually, or just convert your Flow to a `LiveData` for getting the best of both worlds (this extension method is included in the `lifecycle-livedata-ktx` library).

```
class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        viewModel.userName.asLiveData().observe(viewLifecycleOwner) { 
            userName -> userNameLabel.text = userName
        }
    }
}
```

## SharedFlow

You can think of `SharedFlow` as a generalization of `StateFlow`.

- `StateFlow` by default emits the last known value when there's a new subscriber. With `SharedFlow`, you can configure how many previous values to be emitted.
- You can define what happens when the buffer of values is full (e.g. drop values, suspend caller, etc).
- It provides a `subscriptionCount` that indicates how many active collectors exist to define business logic accordingly.
- It provides a `resetReplayCache()` for not emitting the last known values if there are new subscribers.

This offers great flexibility for more advanced use cases that `LiveData` cannot fulfil easily.

## Is it worth it?

The idea is that we can get rid of  Jetpack's `LiveData` and use the platform-independent `StateFlow`/`SharedFlow` in all the layers of an app (view, model, storage). `LiveData` being so Android Lifecycle-depended is no good fit for using it outside of Views/ViewModels.

`StateFlow` API is almost identical to `LiveData` and the `SharedFlow` offers flexibility for more advanced use cases. Since you can get all the advantages of `LiveData` (which is the automatic subscribing/unsubscribing when the app goes to the background) I think that these new APIs are the way to go if you are building a new app.