One Off the Slack: Why Does My List Not Recompose?
Colton Idle has this code:
class ScreenAState {
val people = mutableStateListOf<PersonUIWrapper>()
}
data class PersonUIWrapper(var selected: Boolean, val person: Person)
…as well as:
vm.state.people.forEach {
TextButton(onClick = {
it.selected = true
}) {
if (it.selected) {
Icon(Icons.Default.Check, null)
}
Text(text = it.person.name)
}
Colton’s problem was:
but my code doesn’t recompose, and therefore doesn’t show a checkmark. Is my PersonUIWrapper supposed to use snapshot state internally for it’s two fields?
In general, an ordinary var is unlikely to do what you want, particularly with Compose.
In this case, Colton is modifying selected, and nothing in the system really cares.
It is just a var, and a var is not special. Nothing is paying attention to that var
to do anything when it is changed.
Or, as Joseph-Hawkes-Cates put it:
the mutableStateList will recompose on changes to the list itself rather than changes to the internal state of the values in the list
Slack user nitrog42 pointed to this similar Stack Overflow question.
Google’s Alex Vanyo offered:
To partially answer your original question, if
PersonUIWrapperwas backed by state that was observable to Compose (likemutableStateOf), then this would work like you’d expect.
And that can be preferable as an alternative to the
.copysolution with adata class.
Colton adapted his wrapper to be:
class PersonUIWrapper(val selected: MutableState<Boolean> = mutableStateOf(true), val person: Person)
…but he was not completely happy:
It kind of sucks that I can’t use
byin this case, but using.valueisn’t the worst thing!
Google’s Adam Powell then offered this approach:
class PersonUIWrapper(
selected: Boolean,
val person: Person
) {
var selected by mutableStateOf(selected)
}
Here, selected is both a constructor parameter and a var property backed by the
mutableStateOf() property delegate. The constructor parameter is used for the initial
value of the property. Now, you can refer to selected like an ordinary var, while
it still is a MutableState and participates in the recomposition system.
Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!