State Flow and Shared Flow in Kotlin

<h1>State Flow</h1> <ul> <li><code>StateFlow</code>&nbsp;is a state-holder observable flow that emits the current and new state updates to its collectors.</li> <li>A SharedFlow that represents a read-only state with a single updatable data value that emits updates to the value to its collectors.</li> <li>State flow is designed to be a more efficient and simplified version of Kotlin&rsquo;s existing Flow library, with the key difference being that it represents a single value that can be updated over time, whereas Flow represents a sequence of values.</li> <li>State flow uses a similar syntax to Flow, but instead of emitting a stream of values, it exposes a single value that can be updated using the&nbsp;<code>value</code>&nbsp;property. Changes to this value are automatically propagated to all observers of the state flow.</li> <li>A state flow is a&nbsp;<em>hot</em>&nbsp;flow because its active instance exists independently of the presence of collectors.</li> <li>A&nbsp;<code>StateFlow</code>&nbsp;is always active and in memory, and it becomes eligible for garbage collection only when there are no other references to it from a garbage collection root.</li> <li>A mutable state flow is created using&nbsp;<code>MutableStateFlow(value)</code>&nbsp;constructor function with the initial value.</li> <li>All methods of state flow are&nbsp;<strong>thread-safe</strong>&nbsp;and can be safely invoked from concurrent coroutines without external synchronization.</li> </ul> <p>Let&rsquo;s understand this with an example. Suppose we are fecthing users list from server and then showing that on ui.</p> <p>Step 1: Create model class</p> <pre> data class User(val id: Int, val name: String, val email: String)</pre> <p>Step 2: Make api call in repo</p> <pre> class UserRepository { suspend fun getUserById(userId: Int): User { // make API call to fetch user data val response = // make API call here return response.toUser() // convert API response to User object } }</pre> <p>Step 3: Make this call from ViewModel</p> <pre> class UserViewModel(private val repository: UserRepository) : ViewModel() { private val _user = MutableStateFlow&lt;User?&gt;(null) val user: StateFlow&lt;User?&gt; = _user fun getUserById(userId: Int) = viewModelScope.launch { _user.value = repository.getUserById(userId) } }</pre> <p>Step 4: Observer into the activity</p> <pre> class UserFragment : Fragment() { private val viewModel: UserViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val userId = arguments?.getInt(&quot;userId&quot;) ?: throw IllegalArgumentException(&quot;userId is required&quot;) viewModel.getUserById(userId) viewModel.user.onEach { user -&gt; userTextView.text = user?.name ?: &quot;Loading...&quot; emailTextView.text = user?.email ?: &quot;&quot; }.launchIn(viewLifecycleOwner.lifecycleScope) } }</pre> <p>In this example, the fragment obtains the user ID from its arguments and calls&nbsp;<code>getUserById()</code>&nbsp;on the view model to fetch the user data. The&nbsp;<code>user</code>&nbsp;state flow is then observed using the&nbsp;<code>onEach()</code>&nbsp;function, which updates the UI with the user&#39;s name and email when it becomes available. Note that&nbsp;<code>launchIn()</code>&nbsp;is used to launch the flow in the fragment&#39;s&nbsp;<code>LifecycleScope</code>, which ensures that the flow is cancelled when the fragment is destroyed.</p> <p><a href="https://levelup.gitconnected.com/state-flow-and-shared-flow-in-kotlin-f603c7aa7299">Read More</a></p>
Tags: Kotlin Flow