Issa
03/07/2021, 11:56 AMPathway
first code lab Compose Basics
section Animating your list
I have noticed that LazyColumn
doesn’t remember the isSelected
state of the item when recomposing. I have copy pasted the code from the Pathway
and got the same results. Just when you scroll until the item is no more visible, when you scroll back the isSelected
state is lost. IMO this is wrong cuz the state should be cached anyway and when recomposing the compiler should consider the previous state.
Should I Hoist
the state of the Greeting
widget so I can manage it in the LazyColumn
scope or this is just a Compose Bug
? 🤔
Thanks in advance!jim
03/07/2021, 12:11 PMIssa
03/07/2021, 12:16 PMisSelected
state -> added complexityNamesList
in this case. Now LazyColumn
is not recomposing the items if the state
changes, It only does when the item is being visible on the screen again.
@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {
val selectedStates = remember { mutableStateOf(mutableMapOf<Int, Boolean>()) }
val map = mutableMapOf<Int, Boolean>()
names.forEachIndexed { index, _ ->
map[index] = false
}
selectedStates.value = map
LazyColumn(modifier = modifier) {
itemsIndexed(items = names) { index, name ->
val i: Boolean = selectedStates.value[index] ?: false
Greeting(
name = name,
isSelected = i,
onSelected = {
selectedStates.value[index] = !it
}
)
Divider(color = Color.Black)
}
}
}
jim
03/07/2021, 12:59 PMmutableStateMapOf
instead of mutableMapOf
, else Compose won't know when the map is mutated.Issa
03/07/2021, 1:31 PMremember{}
remembers the state for only one composition invocation, however not recomposition
done by the LazyFoo
apis, cuz these guys they unsubscribe from the previous and init a new invocation which yields a fresh state.
So far here is the code if you want to update the Pathway
code lab.
@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {
val selectedStates = remember {
mutableStateMapOf<Int, Boolean>().apply {
names.mapIndexed { index, _ ->
index to false
}.toMap().also {
putAll(it)
}
}
}
LazyColumn(modifier = modifier) {
itemsIndexed(items = names) { index, name ->
Greeting(
name = name,
isSelected = selectedStates[index] == true,
onSelected = {
selectedStates[index] = !it
}
)
Divider(color = Color.Black)
}
}
}
Thanks again for your help 😉Jorkoh
03/07/2021, 2:03 PMAndrey Kulikov
03/07/2021, 2:08 PMrememberSaveable
instead of remember
the state would survive the item being scrolled off and onIssa
03/07/2021, 5:56 PMrememberSaveable
api a try this sounds really interesting!! @Andrey KulikovrememberSaveable()
It behaves similarly to remember, but the stored value will survive the activity or process recreation using the saved instance state mechanism (for example it happens when the screen is rotated in the Android application).
I am wondering if abusing this patter with say 1000 items in a list where each item is using rememberSaveable
under the hood, I am wondering if this has any performance penalties? 🤔
Other than that… I loved the idea and it was exactly what I was looking for! Thanks again!Andrey Kulikov
03/07/2021, 6:33 PMIssa
03/07/2021, 7:46 PMAndrey Kulikov
03/07/2021, 7:52 PMIssa
03/08/2021, 10:10 AMisSelected
state, it might be more complex depending on the UI. So I thought maybe by creating a ViewHolder
like API, it would be easier to hold the state. I am not sure if this is the responsibility of the item itself or the LazyColumn