Recomposition in Jetpack Compose
Recomposition in Jetpack Compose
Recomposition is the process by which Jetpack Compose re executes composable functions when their input state changes. Rather than rebuilding the entire UI tree, the Compose runtime tracks which composable functions read which state objects and re invokes only those functions whose inputs have changed. This selective update mechanism is called smart recomposition and it is fundamental to Compose's performance model. By the end of this lesson, you will be able to:
- Explain how the Compose runtime tracks state reads and triggers recomposition.
- Describe the role of
remember,mutableStateOf, andderivedStateOfin state management. - Identify what makes a composable function skippable during recomposition.
- Apply best practices to minimize unnecessary recompositions.
- Use compiler reports and the Layout Inspector to diagnose recomposition performance issues.
How Recomposition Works
Composable functions are not called once and forgotten. The Compose runtime maintains a data structure called the slot table that stores the current state and output of each composable invocation. When a state object changes, the runtime marks every composable that read that state object as invalid. On the next frame, it re executes only those invalid composables.
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Column {
Text("Count: $count")
Button(onClick = { count++ }) {
Text("Increase")
}
}
}
When the button is clicked, count changes. The runtime knows that the Text("Count: $count") composable read count, so it re executes that part of the tree. The Button composable and its label do not read count directly, so whether they recompose depends on whether the runtime can determine their inputs are unchanged.
The runtime uses the slot table to compare previous and current values. If a composable's inputs have not changed and the composable is marked as skippable by the compiler, recomposition is skipped entirely for that subtree. This is what makes Compose efficient for complex UIs with many components: only the parts that actually depend on changed state are re executed.
State Tracking with remember and mutableStateOf
mutableStateOf creates a state object that the Compose runtime can observe. When a composable function reads from this state during execution, the runtime records the dependency. When the state value changes, all recorded readers are invalidated.
remember stores a value in the slot table so it persists across recompositions. Without remember, a new mutableStateOf would be created on every recomposition, losing the current value:
// Correct: state survives recomposition
var text by remember { mutableStateOf("") }
// Wrong: state resets on every recomposition
var text by mutableStateOf("")
derivedStateOf creates a derived state that only triggers recomposition when its computed result changes, not when its inputs change:
This interview continues for subscribers
Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.
Become a Sponsor