Skip to content

Collect state in Compose

Hub › Android › Intermediate › Collect state in Compose

Goal

Collect the StateFlow<UiState> from the ViewModel inside a composable and branch on the result. After this page you have a screen that reacts to Loading, Content, and Error without any manual lifecycle handling.

Prerequisites

collectAsStateWithLifecycle

collectAsStateWithLifecycle (from androidx.lifecycle:lifecycle-runtime-compose) converts a Flow into a Compose State. It does two things a plain collectAsState cannot:

  • It stops collecting when the composable's lifecycle owner (the Activity or Fragment) moves to the background, preventing wasted work while the app is not visible.
  • It resumes collecting automatically when the lifecycle comes back to the foreground.
kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun BookListScreen(
    viewModel: BookViewModel = viewModel(),
    onBookClick: (Int) -> Unit,
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    when (val s = state) {
        is UiState.Loading -> LoadingView()
        is UiState.Error   -> ErrorView(s.message, onRetry = viewModel::load)
        is UiState.Content -> BookList(s.books, onBookClick)
    }
}

Because UiState is a sealed interface, the compiler warns on any missing branch here — add a new state and this when flags it until you handle it. (Assign the when to a value to make exhaustiveness a hard error instead of a warning.)

val s = state captures the current value into a local variable so smart-casting works correctly inside each branch (Kotlin cannot smart-cast a by-delegated property directly).

viewModel()

viewModel() (from androidx.lifecycle:lifecycle-viewmodel-compose) retrieves the nearest BookViewModel from the ViewModelStore. If none exists it constructs one. The instance survives recompositions and configuration changes (screen rotation) — the ViewModel is not recreated when the composable recomposes.

What the three helpers are

LoadingView, ErrorView, and BookList are defined on the next page. They are plain composables; BookListScreen just selects which one to show.

Next05 Loading and error UI