LiveData vs StateFlow

Flow and StateFlow Junior Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

A team moves its ViewModels to StateFlow and the screen now updates while it's in the background. What did they lose?

Options
Hint 1 of 1

What did LiveData's observe(owner) do that collect doesn't?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Lifecycle awareness: they must collect with repeatOnLifecycle or collectAsStateWithLifecycle

Correct. LiveData stopped dispatching below STARTED; StateFlow needs a lifecycle-aware collector.

Why not the others?
  • B Thread safety: StateFlow isn't thread-safe. StateFlow is safe to update from any thread.
  • C The initial value. StateFlow requires one; LiveData is the one that may not have it.
  • D Nothing; StateFlow stops in the background on its own. It doesn't know about lifecycles at all.

30-second answer

New Kotlin apps generally use StateFlow. It is part of coroutines, works in plain Kotlin modules and Kotlin Multiplatform, has a rich operator set, and always has an initial value. LiveData is lifecycle-aware on its own, but StateFlow gets the same safety from repeatOnLifecycle or collectAsStateWithLifecycle. LiveData still works fine in existing Java or View code.

Practise saying it · 35 s. No recording, just a timer

Compare LiveData and StateFlow.

Say your answer out loud, then check which of these points you covered:

  • StateFlow is the default for new Kotlin code
  • Works in KMP and plain modules
  • Needs a lifecycle-aware collector
  • LiveData isn't deprecated

Deep dive

LiveData is Android-only, so it can't be used in a domain module or shared KMP code.

LiveData's value can be null before the first set; StateFlow requires an initial value.

asLiveData() and asFlow() convert between them during a migration.

Data Binding can observe StateFlow when you set a lifecycle owner on the binding.

Common mistakes

  • Saying LiveData is deprecated; it isn't, it's just not the default for new Kotlin code.
  • Collecting StateFlow in lifecycleScope.launch without repeatOnLifecycle, losing LiveData's safety.
  • Using observeAsState in a new Compose screen instead of collecting a StateFlow.

Senior take & follow-ups

Avoid absolutes. Give the reasons (KMP, operators, initial value) and the migration path.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you migrate gradually?

    Show hint

    Convert at the edges with asLiveData() or asFlow().

  2. What did LiveData give for free?

    Show hint

    It stops dispatching when the observer is not at least STARTED.

Suggest a fix if something here is wrong or out of date.