Reactive Streams on Kotlin: SharedFlow and StateFlow
In this tutorial, you’ll learn about reactive streams in Kotlin and build an app using two types of streams: SharedFlow and StateFlow. By Ricardo Costeira.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Reactive Streams on Kotlin: SharedFlow and StateFlow
30 mins
- Getting Started
- SharedFlow
- Handling Shared Events
- Event Emission With SharedFlow
- Replay and Buffering
- Subscribing to Event Emissions
- Collecting the SharedFlow
- Applying the Stream Data to the View
- SharedFlow and Channels
- StateFlow
- Handling App State
- Event Emission With StateFlow
- Subscribing to State Updates
- StateFlow and Channels
- Hot Flows, RxJava and LiveData
- Challenge: Using SharedFlow To Handle Screen Events
- Where to Go From Here?
Subscribing to State Updates
Open CoinListFragment.kt. Find observeViewStateUpdates()
and update it to:
private fun observeViewStateUpdates(adapter: CoinAdapter) {
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
viewModel.viewState.collect { updateUi(it, adapter) }
}
}
This code is much like what you did with SharedFlow
in the sense that the same logic applies. Despite this, you might worry about the state flow emitting values when the app is in the background. But you don’t need to. It’s true that, because it’s scoped to viewModelScope
, it’ll still emit even without any subscribers as long as the ViewModel
exists. Regardless, state flow emissions are lightweight operations: It’s just updating the value
and notifying all subscribers. Plus, you probably do want the app to show you the latest UI state when it comes to the foreground.
Build and run the app. Everything should work as before because you just refactored the code. Good job on using StateFlow
!
StateFlow and Channels
Like SharedFlow
can replace BroadcastChannel
completely, StateFlow
can replace ConflatedBroadcastChannel
completely. There are a couple reasons for this. StateFlow
is simpler and more efficient than ConflatedBroadcastChannel
. It also has better distinction between mutability and immutability with MutableStateFlow
and StateFlow
.
Hot Flows, RxJava and LiveData
You’re now aware of how both SharedFlow
and StateFlow
work. But are they even useful on Android?
Although they might not bring anything “new”, they provide more direct and efficient alternatives to the table. For instance, wherever you’d use an RxJava‘s PublishSubject
, you can use a SharedFlow
. Or wherever you’d use a BehaviorSubject
, you can probably use a StateFlow
. In fact, if hot event emission is not an issue, StateFlow
can even easily replace LiveData
.
SharedFlow
and StateFlow
objects in to LiveData
as well with the AndroidX lifecycle-livedata-ktx
library. The library provides an extension method asLiveData()
that allows you to convert the flow and expose it as LiveData
for consumption in your view. For more details, see the StateFlow, Flow, and LiveData section of the Android Developers StateFlow and SharedFlow article.
So, putting it in simpler terms:
- If you have some kind of state management, you can use
StateFlow
. - Whenever you have some event stream going on, where it’s not a problem if events aren’t handled by all possible subscribers or past events might not be handled at all, you can use
SharedFlow
.
Challenge: Using SharedFlow To Handle Screen Events
Congratulations! This concludes the tutorial. If you want to go the extra mile, you can also handle the screen-specific events modeled in the CoinListFragmentViewEffects
and CoinHistoryFragmentViewEffects
classes using shared flows. These are events that should be handled exactly once, which means a simple Channel
would fit better — remember that shared flows drop events when there are no subscribers. Still, you can do it with shared flows for practice. If you’re curious, the final project in the project materials has a sample implementation.
Where to Go From Here?
If you want to learn more about StateFlow
and SharedFlow
, you can check their corresponding documentation pages here and here, respectively.
You can also find some information specific to shared and state flows usage on Android in the Android developers page.
If you’re curious about turning cold flows into hot ones, you can check out the following articles:
- A safer way to collect flows from Android UIs
- Things to know about Flow’s shareIn and stateIn operators
Finally, if the challenge section piqued your interest in using Channel
s to handle screen events, you can check out this interesting article on Medium.
I hope you enjoyed this tutorial. If you have any questions, tips or comments, feel free to join the discussion below. :]