What is MVVM, and how do ViewModel, LiveData and StateFlow fit together?
MVVM separates concerns into three layers:
- Model — data and business logic, usually behind a Repository that decides between network and local cache.
- View — the Activity, Fragment, or Composable. It observes state and forwards user events. It should contain no business logic.
- ViewModel — holds and exposes UI state, and survives configuration changes. It must never reference a View or Context that could leak an Activity.
The observable holders:
- LiveData — lifecycle-aware by design. It only emits to active observers and cleans up automatically, which is why it was safe before coroutines matured. It always holds a current value.
- StateFlow — the Kotlin coroutines equivalent, holding a current value and emitting updates. It is not lifecycle-aware by itself, so it must be collected inside
repeatOnLifecycle(STARTED), or withcollectAsStateWithLifecycle()in Compose. Otherwise collection continues while the app is backgrounded, wasting work. - SharedFlow — for one-off events such as showing a snackbar or navigating, where a state holder would replay the event after rotation.
Note: StateFlow is the modern recommendation because it composes with the rest of the coroutines API — operators, combining streams, and structured concurrency — while LiveData does not. The single-event problem is the detail interviewers probe: using StateFlow for navigation events causes the navigation to repeat on rotation.





