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
PersonUIWrapper
was 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
.copy
solution 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
by
in this case, but using.value
isn’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!