When working with Kotlin Coroutines, many developers face an issue where SharedFlow does not emit values as expected. This can lead to confusion, especially for those transitioning from LiveData
or StateFlow
. In this article, we will explore the reasons behind this problem, common pitfalls, and how to properly use SharedFlow in your Android projects. By the end of this guide, you will understand why SharedFlow sometimes does not emit values and how to fix it effectively.

What is SharedFlow?
SharedFlow
is a hot stream introduced in Kotlin Coroutines 1.4.0. Unlike StateFlow
, which always has a current value, SharedFlow is designed to broadcast events to multiple collectors. It is similar to a publish-subscribe mechanism, where one producer can send events to many consumers.
Main characteristics of SharedFlow:
- It does not hold a current value (unlike StateFlow).
- It can be replayed to new subscribers if replay is set.
- It works well for events such as navigation, messages, or UI triggers.
Why SharedFlow Not Emitting Values?
The most common issue developers face is that emit()
seems not to trigger any reaction in the collectors. Let’s break down the main causes:
- No active collectors: SharedFlow will emit values, but if there are no collectors at that moment, the values may not be received (unless replay is configured).
- Replay not set: If you want late subscribers to receive past values, you must configure the
replay
parameter. - Buffer overflow: If SharedFlow is configured with a small buffer and multiple values are emitted quickly, older values may be dropped.
- Incorrect scope or lifecycle handling: Collectors must run within a proper CoroutineScope, such as
lifecycleScope
in Android.
Example Problem: SharedFlow Not Emitting
Here’s a simplified code example where SharedFlow does not emit values:
class MyViewModel : ViewModel() { private val _events = MutableSharedFlow() val events = _events fun sendEvent() { viewModelScope.launch { _events.emit("Hello World") } } }
class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Trigger event viewModel.sendEvent() // Collect events lifecycleScope.launch { viewModel.events.collect { event -> Log.d("SharedFlowTest", "Received event: $event") } } } }
In this example, the collector might not receive the emitted value because sendEvent()
was called before collect()
started. Since the default replay is 0
, the event is lost.
Solution: Using Replay
To fix this, we can configure the SharedFlow with a replay
parameter:
class MyViewModel : ViewModel() { private val _events = MutableSharedFlow(replay = 1) val events = _events fun sendEvent() { viewModelScope.launch { _events.emit("Hello World") } } }
Now, even if the sendEvent()
method is called before the collector starts, the last emitted value will be replayed to the new subscriber.
Best Practices for SharedFlow
- Use
StateFlow
for states, andSharedFlow
for one-time events. - Set
replay
> 0 if you want late subscribers to receive previous values. - Always collect from a lifecycle-aware scope in Android, such as
lifecycleScope
orrepeatOnLifecycle
. - Consider using
buffer
to handle fast emissions.
Comparison: SharedFlow vs StateFlow
The table below summarizes the key differences:
Feature | SharedFlow | StateFlow |
---|---|---|
Holds Current Value | No | Yes |
Replay Support | Yes (configurable) | Always 1 (latest value) |
Best For | Events, navigation, messages | UI state, data binding |
Late Subscribers | Optional (via replay) | Always get latest value |
Conclusion
If you find your Kotlin SharedFlow not emitting values, the issue is usually related to missing collectors, no replay configuration, or lifecycle scope misuse. By properly setting replay, buffering, and collecting within a lifecycle-aware CoroutineScope, you can ensure that your SharedFlow works as intended. For Android development, following these best practices will help you avoid common pitfalls and build more stable apps.
For further details on Kotlin Coroutines, you can check the official documentation at Kotlin Flow Documentation.