Reputation: 71
I'm at Google CodeLabs: And here is the code:
@Composable
fun WaterCounter(
modifier: Modifier = Modifier,
) {
var count by remember { mutableStateOf(0) }
Column(
modifier = modifier.padding(16.dp)
) {
if (count > 0) {
var showTask by remember { mutableStateOf(true) }
if (showTask) {
WellnessTaskItem(
taskName = "Have you taken your 15 minute walk today?",
onClose = { showTask = false })
}
Text(
text = "You've had $count glasses",
modifier = modifier.padding(16.dp)
)
}
Row(
modifier = modifier.padding(top = 8.dp)
) {
Button(
onClick = { count++ },
enabled = count < 10,
) {
Text(text = "add one")
}
Button(
onClick = { count = 0 },
modifier = modifier.padding(start = 8.dp)
) {
Text(text = "Clear water count")
}
}
}
}
I can't get this phrase: "Press the Clear water count button to reset count to 0 and cause a recomposition. Text showing count, and all code related to WellnessTaskItem, are not invoked and leave the Composition. showTask is forgotten because the code location where remember showTask is called was not invoked."
Please help me understand why show task is forgotten? What does it mean "the code was not invoked" and "it leaves the composition"?
Upvotes: 3
Views: 501
Reputation: 67443
Conditional code blocks enter composition when condition is true and leave composition when condition cease to be true. When count is zero that block is removed and next time it enters composition remember stores showTask
with true
value.
For instance the code block below
@Composable fun App() {
val result = getData()
if (result == null) {
Loading(...)
} else {
Header(result)
Body(result)
}
}
these blocks also enter composition based on result is null or not.
Entering Composition means it's a node that starts execution and when a State
that is read in this block is updated recomposition happens which means same block is updated with new value.
when result is null Loading Composable enters composition, let's say it has a progress bar with value when it's increased Loading Composable is recomposed.
when a result comes Loading Composable exits composition
Header(result)
Body(result)
Also, Composable blocks are not necessarily need to be UI related either. You can create a Composable block for with LaunchedEffect to display a SnackBar for instance.
if (count > 0 && count <5) {
// `LaunchedEffect` will cancel and re-launch if
// `scaffoldState.snackbarHostState` changes
LaunchedEffect(scaffoldState.snackbarHostState) {
// Show snackbar using a coroutine, when the coroutine is cancelled the
// snackbar will automatically dismiss. This coroutine will cancel whenever
// if statement is false, and only start when statement is true
// (due to the above if-check), or if `scaffoldState.snackbarHostState` changes.
scaffoldState.snackbarHostState.showSnackbar("count $count")
}
}
This block will enter composition when count is bigger than 0 and stay in composition while count is less than 5 but since it's LaunchedEffect it will trigger once but if count reaches 5 faster than Snackbar duration Snackbar gets canceled because block leaves composition.
You can check when a Composable enters and exits composition with DisposableEffect
And you can check this article for deeper analysis.
https://medium.com/androiddevelopers/under-the-hood-of-jetpack-compose-part-2-of-2-37b2c20c6cdd
Upvotes: 3