Remembering the State in Jetpack Compose
--
When starting to work with Jetpack Compose (now that it is in beta š) and stateful components, we easily get used to define values based on a mutable state which are also remembered. But there are two independent concepts when we write a line of code like below:
var clicks by remember { mutableStateOf(0) }
- mutableState* family functions return an observable value for Compose. It creates a MutableState that allows Compose to magically react when the contained value changes.
- remember on the other hand makes the computation passed to the lambda execute once (not exactly once, but just during the composition). This is valid not just to avoid a state to recreate/reinitialize when the recomposition happens, but also to ācacheā expensive computations.
To get a better understanding of how both functions work together we are going to see what is the result for a set of examples implementing a simple click counter.
Remembering the state
Here we have a remembered state defined under a Surface. The state value is read on a Text contained in a Button:
Surface {
var clicks by remember { mutableStateOf(0) }
Button(onClick = { clicks++ }) {
Text("Clicked $clicks times")
}
}
clicks
value is populated from an observable type (State<T>
) which is also remembered across any recomposition the Surface may experience.
So even if the Surface were recomposed, the value of clicks will be remembered. This is why the counter works as expected.
Donāt remember the state
Letās remove now the remember āwrappingā around the state:
Surface {
var clicks by mutableStateOf(0)
Button(onClick = { clicks++ }) {
Text("Clicked $clicks times")
}
}
It may be surprising/unexpected that the click counter keeps incrementing. Why isnāt the state recreated? Just because the composable that contains it (the Surface) is not being recomposed. And why isnāt the Surfaceā¦