Interview QuestionPractical QuestionFollow-up Questions

StateFlow vs SharedFlow

skydovesJaewoong Eum (skydoves)||7 min read

StateFlow vs SharedFlow

Kotlin's coroutines library provides two hot flow types for sharing data across multiple collectors: StateFlow and SharedFlow. Both emit values regardless of whether any collector is active, but they differ in how they store data, handle duplicates, and serve their consumers. Choosing the wrong one leads to missed events or unnecessary recompositions. By the end of this lesson, you will be able to:

  • Explain how StateFlow holds and emits a single current value.
  • Describe how SharedFlow broadcasts events with configurable buffering.
  • Identify the duplicate suppression behavior of StateFlow and its implications.
  • Choose between the two based on state management vs event broadcasting needs.

StateFlow

StateFlow is a specialized hot flow that always holds exactly one value. It requires an initial value at creation time and emits the current value immediately to every new collector. Updates replace the stored value, and StateFlow uses structural equality (equals) to suppress emissions when the new value is the same as the current one:

val uiState = MutableStateFlow(UiState.Loading)

// Updating the state
uiState.value = UiState.Success(data)

// Duplicate suppression: this does not emit
uiState.value = UiState.Success(data)

New collectors receive UiState.Success(data) immediately without waiting for the next emission. This makes StateFlow the standard choice for representing screen state in a ViewModel. The value property provides synchronous access to the current state at any time, which is useful for reading state outside of a coroutine context.

StateFlow is a subtype of SharedFlow with replay = 1 and a custom equality based duplicate filter. This relationship means you can use StateFlow anywhere a SharedFlow is expected, but the reverse is not true.

The value property on StateFlow provides synchronous access to the current state at any time, even outside a coroutine context. This makes it easy to read the current state in click handlers, lifecycle callbacks, or test assertions without needing to collect the flow.

SharedFlow

SharedFlow is a general purpose hot flow that broadcasts values to all active collectors. Unlike StateFlow, it does not hold a persistent current value and does not suppress duplicates. Every call to emit delivers the value to all collectors:

val events = MutableSharedFlow<UiEvent>()

// Both emissions are delivered
scope.launch {
    events.emit(UiEvent.ShowSnackbar("Saved"))
    events.emit(UiEvent.ShowSnackbar("Saved"))
}

This interview continues for subscribers

Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.

Become a Sponsor