ViewModel & UI State Interview Questions
ARCHITECTURE › Components
Walk me through how you'd structure a ViewModel's exposed state when a screen has several independent pieces of state, like a list, a loading flag, and a selected filter, versus exposing one combined UiState. What are the trade-offs?
What a strong answer covers: A single immutable UiState data class is generally preferred because it guarantees the UI always renders a consistent, atomic snapshot and lets you exhaustively branch on it, whereas several independent StateFlows can momentarily disagree with each other and force the UI to reconcile partial updates itself. The trade-off is that a combined state class can trigger broader recomposition than necessary; the trap is exposing many separate mutable flows for convenience and ending up with inconsistent state combinations that are hard to test.
How do you unit test a ViewModel that exposes a StateFlow and internally launches coroutines in viewModelScope?
What a strong answer covers: You swap Dispatchers.Main for a TestDispatcher via Dispatchers.setMain in setup (and reset it in teardown), drive the test with runTest so virtual time advances coroutines deterministically, and use something like Turbine to collect and assert the sequence of StateFlow emissions rather than just the final value. A common miss is forgetting to advance or drain the dispatcher before asserting, or never resetting the main dispatcher, which leaves tests flaky or leaking state into later tests.
When would you scope a ViewModel to a navigation graph instead of a single screen, and what problems can that introduce?
What a strong answer covers: A nav-graph-scoped ViewModel makes sense when several screens in one flow, like a multi-step checkout, need to share transient state that shouldn't outlive the flow but also shouldn't be re-created on every step. The risk is that its lifetime is now tied to the whole graph rather than a screen, so if a user jumps out of the flow via deep link or back-stack manipulation, the state can go stale or leak until the graph itself is popped, and it silently couples otherwise-independent screens to a shared instance they must agree exists.