ViewModel, LiveData vs StateFlow, lifecycle-aware components
The ViewModel owns UI state and hosts UI-adjacent business logic. Key properties:
- Survives configuration changes (via the ViewModelStore mechanism)
viewModelScope— a coroutine scope auto-cancelled in onCleared- Must hold no View or Activity-context references (leaks)
- Process-death-resilient state via
SavedStateHandle
LiveData vs StateFlow — the migration question appears in every interview:
- LiveData: lifecycle-aware automatically (delivers at STARTED), Android-bound, poor operators.
- StateFlow: rich Flow operators, KMP-friendly, usable in domain/data layers; lifecycle-awareness needs manual
repeatOnLifecycle.
Lifecycle-aware components (DefaultLifecycleObserver) — the component itself subscribes to the lifecycle and manages its own start/stop; instead of bloating the Activity's onStart/onStop, the observer knows what to do.
// Bank tətbiqində avtomatik logout taymeri
class SessionTimeoutObserver(
private val onTimeout: () -> Unit
) : DefaultLifecycleObserver {
private var job: Job? = null
override fun onStart(owner: LifecycleOwner) {
job = owner.lifecycleScope.launch {
delay(5 * 60_000) // 5 dəqiqə hərəkətsizlik
onTimeout()
}
}
override fun onStop(owner: LifecycleOwner) {
job?.cancel()
}
}
// Activity-də bir sətir:
lifecycle.addObserver(SessionTimeoutObserver { navigateToLock() })A lifecycle-aware component: a session timer managing itself
How the ViewModel survives — they ask for the mechanism: on recreation, the ViewModelStore is passed to the new activity instance via NonConfigurationInstances; the ViewModelProvider finds and returns the existing ViewModel by key. So it is not magic — the store is carried over. onCleared fires only when the user truly leaves the screen (finish, back).
🛠 Practice task
Write a ViewModel with a StateFlow<UiState> + SavedStateHandle.
- Rotate the screen — state survives; kill the process with "Don't keep activities" — the SavedStateHandle field survives, the rest does not. Compare the two.
- Collect without
repeatOnLifecycle(STARTED), background the app and watch the logs keep running; then fix it. - Write a
DefaultLifecycleObserver(e.g. a simple session timer) and attach it vialifecycle.addObserver.
Done when: you can state the boundary between all three mechanisms with an example.
📚 Sources and documentation
- ViewModel overviewofficialdeveloper.android.com
- LiveData overviewofficialdeveloper.android.com
- Lifecycle-aware componentsofficialdeveloper.android.com