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 complexityIssa
03/07/2021, 12:36 PMNamesList 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 KulikovIssa
03/07/2021, 6:07 PMrememberSaveable()
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!Issa
03/07/2021, 6:09 PMAndrey Kulikov
03/07/2021, 6:33 PMAndrey Kulikov
03/07/2021, 6:34 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