Interview QuestionPractical QuestionFollow-up Questions

Saving and Handling UI States in Jetpack Compose

skydovesJaewoong Eum (skydoves)||6 min read

Saving and Handling UI States in Jetpack Compose

Preserving UI state in Jetpack Compose is essential for ensuring a smooth user experience, especially during configuration changes or system initiated process death. Depending on whether the state serves UI logic or business logic, Compose provides different APIs to persist this state across recompositions and lifecycle events. By the end of this lesson, you will be able to:

  • Use rememberSaveable to persist UI state across configuration changes and process death.
  • Apply custom Saver implementations for non primitive types.
  • Use SavedStateHandle in ViewModels for business logic state that survives process death.
  • Integrate SavedStateHandle with StateFlow for reactive state persistence.
  • Choose the right API based on scope and state ownership.

rememberSaveable for UI State

For state related directly to the UI, such as expanded/collapsed flags, text input, or scroll position, rememberSaveable is the recommended tool. It uses the instance state Bundle under the hood to persist data across activity recreation:

@Composable
fun ChatBubble(message: Message) {
    var showDetails by rememberSaveable {
        mutableStateOf(false)
    }

    ClickableText(
        text = AnnotatedString(message.content),
        onClick = { showDetails = !showDetails }
    )

    if (showDetails) {
        Text(message.timestamp)
    }
}

rememberSaveable works automatically for primitive types, strings, and Parcelable objects. For custom types that are not directly serializable to a Bundle, you can provide a Saver:

@Composable
fun rememberLazyListState(
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    return rememberSaveable(saver = LazyListState.Saver) {
        LazyListState(
            initialFirstVisibleItemIndex,
            initialFirstVisibleItemScrollOffset
        )
    }
}

Avoid saving large or complex objects in rememberSaveable. The Bundle has a size limit, and exceeding it causes TransactionTooLargeException. Store lightweight IDs or flags and rehydrate full content from persistent layers.

SavedStateHandle for ViewModel State

When state is hoisted to a ViewModel to support business logic or screen wide state, SavedStateHandle persists values across process death. The saveable API provides a MutableState interface that integrates directly with Compose:

This interview continues for subscribers

Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.

Become a Sponsor