---
title: "🌊 StateFlow, End of LiveData? | Shreyas Patil's Blog"
description: "Is StateFlow the end of LiveData? An opinionated look at how Kotlin's StateFlow is replacing LiveData for state management in Android."
image: "https://blog.shreyaspatil.dev/_astro/cover-stateflow-end-of-livedata-a473094229b3.BFUu2tbb.jpeg"
---

# 🌊 StateFlow, End of LiveData?

In this article, we’ll learn how to use Kotlin Coroutine `StateFlow` in Android instead of `LiveData`.

In the recent release of Kotlin coroutines library (1.3.6), you can see there a new class — `StateFlow`. So what’s this and how it works? Let’s see…

---

## What is `StateFlow`? 🤷‍♂️

*It’s basically a new primitive for state handling.* It’s designed to eventually replace [`ConflatedBroadcastChannel`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-conflated-broadcast-channel/index.html) for state publication scenarios.

*It is a **flow** that emits updates to its collectors.* Value can be observed by collecting values from the **flow** 🌊.

---

## Still not getting? Here’s a quick demo to understand —

See [this demo program](https://pl.kotl.in/LWtbOSMEZ?theme=darcula) and play with it.

I think now you get it what’s exactly — `StateFlow` 😃. So what’s happening here is whenever we’re updating the value of **stateFlow** then it emits value to its *collectors*.

To manage state in Android we generally used Android Arch. component’s [`LiveData`](https://developer.android.com/topic/libraries/architecture/livedata) which is lifecycle-aware. We can replace it with *StateFlow*. Let’s see how to use it with Android. Let’s write some code!

---

## ⚡️ Getting Started

Open *Android Studio* and create a new project. Alternatively, you can simply clone [this repository](https://github.com/scalereal/StateFlow-Demo). This is a very simple *counter* app for demonstrating the use of Kotlin Coroutine’s *StateFlow* API.

We’ll be using `MainViewModel` to manage our data of `MainActivity`.

```
@ExperimentalCoroutinesApi
class MainViewModel : ViewModel() {
    private val _countState = MutableStateFlow(0)

    val countState: StateFlow<Int> = _countState

    fun incrementCount() {
        _countState.value++
    }

    fun decrementCount() {
        _countState.value--
    }
}
```

Now you can compare its implementation using *LiveData*.

*`MutableStateFlow` has a setter property for **value**.* We’ve declared an instance of `StateFlow` i.e. *countState* which we’re exposing for activity (*It’s a read-only field*). `StateFlow` has a property called **value** by which you can be safely read at any time.

Now let’s implement our `MainActivity` —

```
class MainActivity : AppCompatActivity() {

    private val viewModel by lazy {
        ViewModelProvider(this)[MainViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initCountObserver()
        initView()
    }
}
```

Here, we’ve initialized ViewModel for activity. Now let’s implement the `initView()` method which will initialize our Counter App UI.

```
private fun initView() {
        button_plus.setOnClickListener(::incrementCounter)
        button_minus.setOnClickListener(::decrementCounter)
    }

    private fun incrementCounter(view: View) {
        viewModel.incrementCount()
    }

    private fun decrementCounter(view: View) {
        viewModel.decrementCount()
    }
```

Everything looks cool now! 😃. Let’s observe for count value now to keep track of counting and show it on UI accordingly.

```
private fun initCountObserver() {
        lifecycleScope.launch {
            viewModel.countState.collect { value ->
                textview_count.text = "$value"
            }
        }
    }
```

Here’s we have collector which will be executed whenever the value of a *countState* is updated. We also made it **lifecycle-aware** as we’ve used it under `lifecycleScope`. It looks simple, right? That’s it! 😎

Now let’s run this app and see if it’s working:

![](https://blog.shreyaspatil.dev/_astro/img-0964a8c5.DTqABi1c_ZaN3h9.webp)

*Counter app demo*

Ain’t it Sweettttt 😍.

---

## We can implement the same using LiveData too. What’s different then? 🤷‍♂️

We can use powerful *flow* operators with `StateFlow` like ***combine, zip, etc*** which can give us more great experience than *LiveData*. Yes, that’s it.

---

## Final Words

- `StateFlow` is really easy to handle and implement. Currently, it doesn’t support LiveData’s `onActive()` or `onInactive()` like callbacks but this will be possible once [`SharedFlow`](https://github.com/Kotlin/kotlinx.coroutines/issues/2034) is officially released 🚀.

- Its behaviour is the same as `LiveData` along with more operators and great performance 😎. Then we should consider using it instead of LiveData.

If you found this helpful please give some claps 👏 and share it with everyone.

*Sharing is Caring!*

Thank You :) 🙏

If you need any help, you can contact me [here](https://patilshreyas.dev/).

---

## 📚 Resources

- [StateFlow Demo - GitHub](https://github.com/scalereal/StateFlow-Demo)

- [StateFlow Documentation](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/index.html)

```json
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "🌊 StateFlow, End of LiveData? | Shreyas Patil's Blog",
  "image": "https://blog.shreyaspatil.dev/_astro/cover-stateflow-end-of-livedata-a473094229b3.BFUu2tbb.jpeg",
  "datePublished": "2020-05-22T15:49:15.659Z",
  "author": [
    {
      "@type": "Person",
      "name": "Shreyas Patil",
      "url": "https://shreyaspatil.dev/"
    }
  ],
  "keywords": "others"
}

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://blog.shreyaspatil.dev/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Posts",
      "item": "https://blog.shreyaspatil.dev//posts/"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "🌊 StateFlow, End of LiveData?"
    }
  ]
}
```
