Saving and Handling UI States in Jetpack Compose
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
rememberSaveableto persist UI state across configuration changes and process death. - Apply custom
Saverimplementations for non primitive types. - Use
SavedStateHandlein ViewModels for business logic state that survives process death. - Integrate
SavedStateHandlewithStateFlowfor 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