Skip to content

StateFlow in Android

Published: at 7 min read

Table of contents

Open Table of contents

What is stateFlow

StateFlow is a part of the Kotlin Flow library to manage and represent a state in an application.

Lets go for a simple example :

considering two values a and b where a is the value initially emitted and b is the value to be emitted.

if (a == b) the do nothing
else if(a != b) return b

We can think of StateFlow like the Subject in RxJava

Knowing more about stateFlow

1. A state flow is a hot flow because its active instance exists in memory independently of the presence of collectors.

2. Its current value can be retrieved via the **value** property.

3. In Android, StateFlow is a great fit for classes that need to maintain an observable mutable state.

4. StateFlow is specifically designed for managing and observing states in Android applications.

5. It's often used as an alternative to LiveData for managing UI-related data.

6. StateFlow is used when one needs to maintain and share a single source of truth for a state and automatically update all collectors with the latest state.

stateFlow

Why StateFlow is used

Stateflow enables you to design and develop supervisory control, task scheduling, fault management, communication protocols, user interfaces, and hybrid systems. In Android, StateFlow is a great fit for classes that need to maintain an observable mutable state.

Lifecycle of StateFlow

lifecycle

  1. Creation: A StateFlow is created and initialized, usually within a ViewModel or another data management component. This typically happens when the associated Android component (e.g., Activity or Fragment) is created.

  2. Observation: The component that needs to observe the StateFlow subscribes to it, often in the onCreate or onCreateView method of an Android component. This is where you register observers using functions like collect, onEach, or launchIn.

viewModel.myStateFlow.collect { state ->
    // Handle state changes
}
  1. Updating State: The StateFlow is updated as needed, often in response to user interactions or data changes. One can use functions like value (for mutable StateFlow) or update it within a coroutine.
viewModel.updateState("New Value")
  1. Observation Continues: The observers continue to receive updates from the StateFlow as long as they are active and the StateFlow itself is still in scope.

  2. Lifecycle Events: When the Android component (Activity or Fragment) that holds the StateFlow is destroyed or no longer needed, it goes through its lifecycle events, such as onPause, onStop, onDestroy, or onDestroyView. It’s essential to handle the lifecycle events correctly to avoid memory leaks.

  3. Cancelling Observers: To prevent resource leaks and unnecessary updates, it’s a good practice to cancel the observation of the StateFlow when the component is no longer active.

override fun onCleared() {
    super.onCleared()
    // Cancel all active coroutines, including StateFlow    observations
    viewModelScope.cancel()
}
  1. Cleanup: Any cleanup tasks related to the StateFlow can be performed in the appropriate lifecycle event (e.g., onDestroy or onDestroyView) of the Android component.

Why Stateflow is more efficient than Livedata

StateFlow and LiveData serve similar purposes in Android development by allowing you to observe and react to changes in data. While both are useful, StateFlow has certain advantages that make it more efficient and a preferred choice in some scenarios:

The choice between StateFlow and LiveData depends on your specific project requirements and whether you want to adopt Kotlin Flow and coroutines as part of your development stack. In many cases, StateFlow is preferred for its flexibility and efficiency when working with asynchronous data streams.

How this MutableStateFlow arrives

class CounterModel {
    private val _counterData = MutableStateFlow(0) // private mutable state flow
    val counterData = _counterData.asStateFlow() // publicly exposed as read-only state flow

    fun inc() {
        _counterData.update { count -> count + 1 } // atomic, safe for concurrent use
    }
}

Here are some drawbacks of StateFlow

1. StateFlow collect emit NullPointerException.
2. StateIn operator doesn't update the cached value of StateFlow.
3. Whenever the value is accessed, the value from all StateFlows is calculated, which can be problematic if heavy computation is happening while calculation.

StateFlow usage in Android Kotlin

Here’s a brief overview of how to use StateFlow in Android Kotlin:

  1. Add the necessary dependencies to your app’s build.gradle file:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
implementation "androidx.lifecycle:lifecycle-viewmodel:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata:2.3.1"
  1. Create a ViewModel class for your UI component that will hold the StateFlow.
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class MainViewModel : ViewModel() {
    private val _myStateFlow = MutableStateFlow<String>("Initial Value")
    val myStateFlow: StateFlow<String> = _myStateFlow

    fun updateUIState(newValue: String) {
        viewModelScope.launch {
            _myStateFlow.value = newValue
        }
    }
}

In this example, we have a ViewModel with a StateFlow called myStateFlow. You can initialize it with an initial value and use viewModelScope to safely update the state in a coroutine.

  1. In your Activity or Fragment, create an instance of the ViewModel and observe the StateFlow.
import androidx.lifecycle.ViewModelProvider
import kotlinx.coroutines.flow.collect

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel

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

        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        viewModel.myStateFlow.collect { state ->
            // Handle the updated state here
            // This will be called whenever the state changes
            updateUI(state)
        }

        // Example: Update the state
        viewModel.updateUIState("New Value")
    }

    private fun updateUI(state: String) {
        // Update your UI components with the new state
    }
}

In this example, we create an instance of the ViewModel using ViewModelProvider and then observe the StateFlow using the collect function. Whenever the state changes, the updateUI function will be called, allowing you to update your UI accordingly.

Summary

StateFlow is a powerful tool for managing and observing the state of your Android application. It provides a more reactive and concise way to handle state changes compared to traditional LiveData.

Share :
Written by:Parita Dey

Interested in Writing Blogs, showcase yourself ?

If you're passionate about technology and have insights to share, we'd love to hear from you! Fill out the form below to express your interest in writing technical blogs for us.

If you notice any issues in this blog post or have suggestions, please contact the author directly or send an email to hi@asdevs.dev.