Reputation: 2290
I'm exploring Compose Recomposition with an Experience composable, and I'm a bit confused about its behavior.
In the first code snippet, Experience() was not recomposed after the button click:
@Composable
fun Experience() {
println("Expericence() : Recomposition")
var j = 5
var i by remember { mutableIntStateOf(5) }
Row {
Button(
onClick = {
i++
j++
var text = "i=$i j=$j"
println(text)
}
) {
var text = "i=$i j=$j"
println("Button() : Recomposition")
Text(text)
}
}
}
However, in this second snippet, Experience() is recomposed:
@Composable
fun Experience() {
println("Expericence() : Recomposition")
var j = 5
var i by remember { mutableIntStateOf(5) }
Row {
var text = "i=$i j=$j"
Button(
onClick = {
i++
j++
println(text)
}
) {
println("Button() : Recomposition")
Text(text)
}
}
}
Can someone explain why this is happening? In my understanding, in the second code snippet, only Row and its children should be recomposed, not the entire Experience() composable.
Upvotes: 1
Views: 317
Reputation: 1723
I suggest reading the article What is “donut-hole skipping” in Jetpack Compose?. It's exactly your usecase
To answer your question, the recomposition happens because you read the i
variable inside Row {}
in your second snippet.
Compose will recompose to the nearest scope. Normally, that'd be Row
, however, Row
is inline
, so the nearest scope is your Experience
composable
Upvotes: 3
Reputation: 20646
Recomposition happens when any part of a Composable
function changes, then the entire composable is recomposed.
Even if you extracted the Text
into a variable, the reference to the text is still within the scope of the Button
's lambda, and then it changes.
Even if you moved the Text variable outside the Button
's lambda it is not a part of the lambda's scope, now, changes to i and j will only trigger recomposition of the Button
and its childrens, not the entire Experience
composable.
If you want to avoid recomposition you may use derivedStateOf
to create a derived state that only depends on the specific variables you want.
val buttonText by remember(i, j) {
derivedStateOf {
"i=$i j=$j"
}
}
Upvotes: 0