MVVM & Unidirectional Data Flow Quiz

ARCHITECTURE › Patterns

In unidirectional data flow, which statement correctly describes the directions?

Answer: State flows down to the View; events flow up to the ViewModel

UDF means state is produced by the ViewModel and flows down to the UI, while user events flow up to the ViewModel, which processes them and emits new state.

Why should a ViewModel avoid holding a reference to an Activity, Fragment, or View?

Answer: It outlives them across config changes, risking leaks and hurting testability

A ViewModel survives configuration changes and outlives the View, so holding a View reference leaks it; staying framework-free also keeps the ViewModel JVM-testable.

What is the recommended way to model the complete state of a single screen?

Answer: A single immutable data class exposed as one observable stream

Combining related state into one immutable data class exposed as a single stream gives a consistent single source of truth and fewer inconsistencies than scattered mutable fields.

Which approach best represents loading, success, and error states for a screen?

Answer: Encode them in the immutable UI state, via flags or a sealed interface

Loading, error, and empty conditions are part of what the user should see, so they belong inside the immutable UI state (flags or a sealed hierarchy), keeping a single source of truth.

In Jetpack Compose, how is 'state down, events up' typically implemented for a stateless Composable?

Answer: It takes state as parameters and emits callback lambdas to the caller

State hoisting passes state down as parameters and lifts events up via callbacks, so the Composable stays stateless and the ViewModel owns the state.

Which API is recommended for collecting a ViewModel's StateFlow in the UI so collection respects lifecycle?

Answer: collectAsStateWithLifecycle()

collectAsStateWithLifecycle() collects only while the lifecycle is at least STARTED, avoiding wasted work and updates while the UI is in the background.

According to the single-source-of-truth principle, who should mutate the UI state a ViewModel exposes?

Answer: Only the data owner, the ViewModel itself, should mutate it

Only the source or owner of the data should update it; allowing the View or others to mutate it creates multiple sources of truth and inconsistencies.

What is the idiomatic way for a ViewModel to expose StateFlow-based UI state so the UI cannot mutate it?

Answer: Hold a private MutableStateFlow, exposed read-only via asStateFlow()

Backing the public stream with a private MutableStateFlow and exposing it as a read-only StateFlow enforces that only the ViewModel mutates state, preserving the single source of truth.

When turning a cold Flow from the data layer into a StateFlow in the ViewModel, which operator configuration stops upstream work shortly after the UI goes to the background yet still survives a configuration change?

Answer: stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue)

WhileSubscribed(5000) keeps the upstream active for five seconds after the last collector disappears, long enough to outlive a rotation but short enough to cancel work while the app is backgrounded.

How should one-off UI events such as 'navigate to detail' or 'show a snackbar' be handled relative to the screen's UI state?

Answer: Modeled as consume-once state the UI marks handled so it won't re-fire

Current guidance models events as state that the UI consumes once and notifies the ViewModel about, which prevents a stale event from re-triggering after a recomposition or config change.

Where should business logic (e.g. the rules deciding whether an item can be bookmarked) and UI logic (e.g. formatting a timestamp for display) each live?

Answer: Business logic in the data/domain layer; UI logic in the UI layer

Business logic implements product requirements and lives in the data/domain layers, while UI logic decides how state is presented and belongs in the UI layer, keeping responsibilities cleanly separated.

A ViewModel survives configuration changes but not system-initiated process death. What is the recommended way to retain small pieces of UI state across process death?

Answer: Use SavedStateHandle, which is backed by saved instance state

SavedStateHandle is backed by the saved instance state bundle, so small, critical pieces of state are restored when the system recreates the process, unlike plain ViewModel fields.

What is the safe, idiomatic way to update a single field of an immutable UI state held in a MutableStateFlow when updates may happen concurrently?

Answer: Call update { it.copy(isLoading = true) } for an atomic change

MutableStateFlow.update {} performs a thread-safe compare-and-set, and copy() yields a new immutable instance with just the changed field, avoiding lost updates from a non-atomic read-modify-write.

Which property of StateFlow makes it a natural fit as a UI-state holder compared with a plain SharedFlow?

Answer: It always holds one current value, requires an initial, is conflated

StateFlow always exposes a single current value, requires an initial value, is conflated, and skips emissions when the new value equals the previous one, which matches how a screen's state should behave.

Back to MVVM & Unidirectional Data Flow