Skip to content
tezvyn:

Hot vs. Cold Streams: `StateFlow` vs. `Flow`

Source: developer.android.comMediumHow cards are made

Hot vs. Cold Streams: `StateFlow` vs. `Flow`

Tests your grasp of stream lifecycles. A great answer defines cold Flow (lazy, per-collector) vs. hot StateFlow (shared, active), then uses a ViewModel UI state scenario to show why StateFlow is correct for surviving configuration changes.

What's really being asked

This question tests your understanding of stream lifecycles, resource management, and state sharing in coroutines, not just rote definitions. The interviewer wants to see if you can articulate the fundamental difference in behavior (lazy vs. eager, unicast vs. multicast) and apply it correctly to the most common Android architecture pattern: managing UI state in a ViewModel.

The full answer

First, define a cold Flow. It's a blueprint for creating a stream. It's lazy, meaning the code inside the flow { ... } builder does not run until a terminal operator like collect is called. Each collector triggers a new, independent execution of the flow. Think of it as a recipe; every cook follows it from the start.

Second, define a hot stream like StateFlow or SharedFlow. It's a live data source that is active and emitting items regardless of whether there are any collectors. Multiple collectors can listen to the same stream and will receive the same values. Think of it as a live TV broadcast; viewers tune in to what's currently airing.

Third, explain the specific role of StateFlow. It's a specialized hot flow designed to represent a single, updatable state value. It always has an initial value, replays its last value to any new collector, and its values are distinct by default (.distinctUntilChanged() is built-in). This makes it perfect for holding UI state.

Fourth, give the practical Android scenario. A ViewModel needs to expose the screen's state (e.g., loading status, a list of items). This state must survive configuration changes (like screen rotation). By exposing state as a StateFlow, the state is held in the ViewModel even when the UI (Fragment/Activity) is destroyed and recreated. The new UI instance simply collects the flow and immediately receives the most recent state, seamlessly updating itself without needing to re-trigger a data fetch. A cold Flow would restart its producer block for the new UI instance, causing an unnecessary and often expensive data reload.

The mistakes people make

Giving vague definitions like "hot is shared, cold is not" without explaining the lazy vs. eager execution model. The core mistake is not understanding that a cold Flow in a ViewModel would re-execute its entire upstream logic (e.g., a network call) for every new collector, such as after a screen rotation. Another red flag is confusing StateFlow with LiveData without mentioning the key difference: LiveData is lifecycle-aware automatically, whereas StateFlow collection from a UI must be explicitly managed within a lifecycle-aware coroutine scope, typically using repeatOnLifecycle.

What usually comes next

"When would you use SharedFlow instead of StateFlow?" (For one-time events that shouldn't be replayed, like showing a Snackbar message). "How do you turn a cold Flow into a hot one, and what is SharingStarted.WhileSubscribed(5000)?" (Using stateIn() or shareIn(). The 5-second timeout keeps the upstream flow active during brief interruptions like configuration changes, preventing costly restarts).

A concrete example

In a ViewModel, you expose state: private val _uiState = MutableStateFlow(UiState.Loading); val uiState: StateFlow<UiState> = _uiState.asStateFlow(). In a Fragment, you collect it safely: viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.uiState.collect { state -> updateUi(state) } } }. If uiState were a cold Flow from a repository, rotating the screen would cause the repository's data-fetching logic to run again.

Interview question

Why is `StateFlow` preferred over a cold `Flow` in a ViewModel for exposing UI state that must survive screen rotation?

  • a.`StateFlow` is automatically lifecycle-aware, preventing updates when the app is backgrounded, unlike a cold `Flow`.
  • b.Using a cold `Flow` in a ViewModel is deprecated and causes memory leaks, whereas `StateFlow` is the modern, safer replacement.
  • c.A cold `Flow` would re-execute its data production logic for the new UI after rotation, while `StateFlow` holds the existing state.Correct
  • d.A cold `Flow` can only have one collector at a time, but `StateFlow` allows multiple UI components to observe the state.
Why?

`StateFlow` is a hot, state-holding stream. It maintains its value across UI recreations, providing the latest state to the new UI. A cold `Flow` would restart its producer logic for the new UI collector, causing an unnecessary data reload. The most tempting distractor is the lifecycle-awareness claim, which is true for `LiveData`, not `StateFlow`.

Just read this? Test yourself on what you have been reading.

Read the original → developer.android.com

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on android — each one lists the topics its interview covers.

See open roles