ViewModel & UI State Quiz

ARCHITECTURE › Components

An app is rotated, then later killed by the OS while in the background and restored. Which mechanism preserves state across BOTH events?

Answer: A ViewModel with state kept in SavedStateHandle

The ViewModel handles the rotation (config change), and SavedStateHandle persists the value to the saved-state Bundle so it survives system-initiated process death and restoration.

Why is injecting an Activity Context into a ViewModel considered a bug?

Answer: A ViewModel can outlive the Activity, so it leaks the destroyed one

Because a ViewModel survives configuration changes, it can outlive the Activity that created it; retaining the Activity Context leaks that destroyed instance.

What is the correct way to expose screen state from a ViewModel for unidirectional data flow?

Answer: Keep a private MutableStateFlow and expose it with asStateFlow()

A private MutableStateFlow exposed read-only via asStateFlow() lets the UI observe but not mutate state, preserving unidirectional data flow.

What happens to coroutines launched in viewModelScope when the ViewModel is cleared?

Answer: They are cancelled automatically when onCleared() runs

viewModelScope is cancelled as part of clearing the ViewModel, so all coroutines launched in it are automatically cancelled without manual cleanup.

Which scenario does NOT require you to write a custom ViewModelProvider.Factory?

Answer: The ViewModel is annotated @HiltViewModel with an @Inject constructor

Hilt generates the ViewModel factory at compile time for @HiltViewModel classes, so you do not write one; the other cases need a factory to supply dependencies.

Inside a viewModelFactory { initializer { ... } } block, how do you obtain a SavedStateHandle for the ViewModel?

Answer: Call createSavedStateHandle()

createSavedStateHandle() builds a SavedStateHandle from the CreationExtras inside the initializer; constructing one directly would not be wired to saved state.

Which value can be stored in SavedStateHandle so it reliably survives process death?

Answer: A Parcelable data class instance

SavedStateHandle serializes to a Bundle, so values must be Bundle-compatible such as primitives, Parcelable, or Serializable; Views, network calls, and lambdas are not persistable.

When is a ViewModel's onCleared() actually called?

Answer: Only when its ViewModelStoreOwner is permanently destroyed for good

onCleared() runs when the ViewModelStoreOwner is finished for good, not on config changes (the whole point is the ViewModel is retained across rotation), and not merely when backgrounded.

Two Fragments hosted in the same Activity need to read and update the same screen state. What is the idiomatic way to share one ViewModel instance between them?

Answer: Both Fragments use by activityViewModels() for one Activity-scoped instance

by activityViewModels() scopes the ViewModel to the Activity's ViewModelStore, so both Fragments obtain the same instance and share state; per-Fragment viewModels() would create separate instances.

You want a value stored in SavedStateHandle to drive Compose UI and recompose whenever it changes. Which API is the right choice?

Answer: Use savedStateHandle.getStateFlow(key, default) to get an observable StateFlow

getStateFlow(key, default) exposes the saved value as an observable StateFlow that re-emits whenever the key is updated, so the UI reacts automatically while still surviving process death.

In Compose, why is collectAsStateWithLifecycle() generally preferred over collectAsState() for a ViewModel's StateFlow?

Answer: It collects only while lifecycle is at least STARTED, then pauses

collectAsStateWithLifecycle() is lifecycle-aware: it stops collecting when the host drops below STARTED (e.g., screen backgrounded) and resumes later, avoiding wasted work; plain collectAsState() collects regardless of lifecycle.

A ViewModel genuinely needs a Context (for example to read string resources). What is the safe way to obtain one?

Answer: The Application context via AndroidViewModel or APPLICATION_KEY

The Application context lives as long as the process and never leaks an Activity, so AndroidViewModel or APPLICATION_KEY is the correct source; any Activity-bound context risks leaking the destroyed Activity.

A ViewModel needs to emit a one-time 'navigate to the next screen' signal. Why is putting it in a StateFlow<UiState> problematic, and what fits better?

Answer: StateFlow replays its value, re-firing on rotation; a Channel fits better

Because StateFlow always replays its current value to new collectors, a recomposition or rotation re-triggers the event; a Channel consumed as a Flow (or a SharedFlow with replay 0) delivers each event exactly once.

A repository exposes a cold Flow<List<Item>>. What is the idiomatic way to surface it from a ViewModel as a hot StateFlow that stops upstream collection shortly after the UI goes away?

Answer: Use flow.stateIn(viewModelScope, WhileSubscribed(5000), initialValue)

stateIn with SharingStarted.WhileSubscribed(5000) converts a cold flow into a hot StateFlow scoped to viewModelScope, keeping upstream collection alive only while there are subscribers (plus a short grace window for config changes).

Back to ViewModel & UI State