Anil Sai
Anil Sai
Android Developer

πŸ“‘ Everything You Need to Know About SharedFlow in Android

πŸ“‘ Everything You Need to Know About SharedFlow in Android

πŸ“’ Everything You Need to Know About SharedFlow in Android

As modern Android development evolves, reactive and coroutine-based architectures are taking center stage. While LiveData and StateFlow are great for observing state, SharedFlow is the go-to solution for one-time events, like showing a toast, navigation, or triggering dialogs.

In this post, we’ll explore:

  • What is SharedFlow?
  • SharedFlow vs StateFlow vs LiveData
  • Use cases for SharedFlow
  • How SharedFlow works
  • Code examples
  • Best practices
  • Common pitfalls

πŸ’‘ What is SharedFlow?

SharedFlow is a hot flow introduced in Kotlin Coroutines 1.4.0+ as part of the kotlinx.coroutines.flow package. Unlike StateFlow, which holds and replays the latest value, SharedFlow can emit multiple values and can be configured to replay a specific number of past values to new collectors.

Think of SharedFlow as a coroutine-based event broadcasterβ€”suitable for one-time events like navigation, snackbars, or messages.


πŸ”„ SharedFlow vs StateFlow vs LiveData

Feature SharedFlow StateFlow LiveData
Lifecycle aware ❌ No ❌ No βœ… Yes
Holds latest value ❌ Optional βœ… Always βœ… Yes
Supports multiple collectors βœ… Yes βœ… Yes ⚠️ Limited
Replay values βœ… Customizable βœ… Only latest ⚠️ No
Event support βœ… Ideal for events ❌ Avoid for one-time events ⚠️ Workarounds needed
Coroutine-native βœ… Yes βœ… Yes ⚠️ Optional

πŸš€ Why Use SharedFlow?

  • πŸ”₯ Hot stream β€” always emits even if no one is collecting.
  • 🧡 Coroutine-native β€” works well with viewModelScope and lifecycleScope.
  • πŸ“€ Supports multiple collectors β€” great for broadcasting.
  • βͺ Replay support β€” can replay past values to new collectors.
  • 🎯 Best suited for one-off events β€” like toasts, navigation, and UI signals.

🧬 Anatomy of SharedFlow

SharedFlow is read-only by default, but you use MutableSharedFlow to emit values.

ViewModel setup:

```kotlin class MyViewModel : ViewModel() { private val _events = MutableSharedFlow() val events = _events.asSharedFlow()

1
2
3
4
5
6
7
8
fun sendEvent(message: String) {
    viewModelScope.launch {
        _events.emit(message)
    }
} } Collect in Activity or Fragment: kotlin Copy Edit lifecycleScope.launchWhenStarted {
viewModel.events.collect { event ->
    Toast.makeText(context, event, Toast.LENGTH_SHORT).show()
} } βš™οΈ SharedFlow Configuration MutableSharedFlow can be customized using:

kotlin Copy Edit MutableSharedFlow( replay = 0, // Number of values to replay to new collectors extraBufferCapacity = 0, // Buffer before suspending emitters onBufferOverflow = BufferOverflow.SUSPEND // Strategy: DROP_LATEST, DROP_OLDEST ) Example with replay:

kotlin Copy Edit val messages = MutableSharedFlow(replay = 1) πŸ“¦ Use Cases for SharedFlow 🚦 Navigation events (e.g. navigate to next screen)

πŸ”” One-time messages like snackbars/toasts

βœ… Form submission success

❌ Error reporting

πŸ•ΉοΈ UI triggers (dialogs, modals)

πŸ”§ Real-world Example: Navigation kotlin Copy Edit sealed class UiEvent { data object NavigateToHome : UiEvent() data class ShowToast(val message: String) : UiEvent() }

class MyViewModel : ViewModel() { private val _uiEvent = MutableSharedFlow() val uiEvent = _uiEvent.asSharedFlow()

1
2
3
4
5
fun onLoginSuccess() {
    viewModelScope.launch {
        _uiEvent.emit(UiEvent.NavigateToHome)
    }
} } Collecting in Activity or Compose:

kotlin Copy Edit lifecycleScope.launchWhenStarted { viewModel.uiEvent.collect { event -> when (event) { is UiEvent.NavigateToHome -> navigateToHome() is UiEvent.ShowToast -> Toast.makeText(context, event.message, Toast.LENGTH_SHORT).show() } } } πŸ“Œ Best Practices Always expose SharedFlow as read-only using .asSharedFlow().

Use viewModelScope.launch to emit values safely.

Avoid replaying large values unless necessary.

Prefer SharedFlow over LiveData pattern (which often leads to sticky events).

In Jetpack Compose, remember to collect inside LaunchedEffect or rememberCoroutineScope.

❗ Common Pitfalls

Pitfall Solution No collectors? Emit is suspended. Use extraBufferCapacity > 0 or tryEmit() Multiple toasts/events firing again Set replay = 0 Using for UI state Prefer StateFlow instead Lifecycle issues Collect in lifecycleScope.launchWhenStarted 🧠 Final Thoughts SharedFlow is a powerful addition to Kotlin’s reactive toolkit and fills a critical gap left by LiveData and StateFlow. It’s especially useful when you need event-based communication between ViewModel and UI, without worrying about lifecycle.

comments powered by Disqus