I know its late, but here's what I understand with remember
.
I have a simple Todo app where a list of todos are hoisted in a viewwmodel
using a SnapshotStatelist
, this list is rendered by a LazyColumn
where each todo model
has its own remembered
state
where I do some pretty basic UI functionality (e.g card elevation, visibility of some icons). Any changes I make to a todo should propagate back up to the mutableStateList
(e.g deleting a todo), SnapshotStateList
will then notify the LazyColumn
to perform a recomposition
, however when I edit
a Todo (e.g, modifying the title), I also have to update the item
composable
that holds this todo(some UI changes), then I got stuck up as I can't figure out why the item
composable
is not recomposing
even if I was able to verify that the SnapShotStateList
item is modified by using the code below
val todoList = viewModel.todos
val snapshot = Snapshot.takeMutableSnapshot()
snapshot.enter {
for (todo in todoList) {
Log.e("TodoModel", todo.title)
}
}
Code that modifies the list
val index = todos.indexOfFirst { it.id == modifiedModel.id }
todos[index] = todos[index].copy(//..some properties to be copied)
I verified that any modification I make on a todo reflects back to its host list, but the item
composable
that renders a todo item doesn't trigger a re-composition
. I kept reading some posts and carefully thinking object references and trying to understand my code based on this object reference thought, I thought that there must be something that holds the previous state of the item
and the changes is not applied to the remember
, until I found that you can supply a key
to a remember
where it will be the thing that will decide if remember
needs to re-calculate. Now I found out that remember
only remembers a state (by state I dont mean compose state, but state in general) on initial composition
, it will keep that initial structure/state for as long as the entire composable it is part of is still running, in this case all the way up to the parent composable
(i.e my DashboardScreen), what made my remember
re-calculate is I supplied the key with the todo object itself
val itemState: ItemCardState = remember(key1 = todoModel) {
ItemCardState(todoModel = todoModel)
}
This way, when a change happens to the SnapShotStateList
, an item
's remember
will see the same object reference (data class) but with changes applied to it. remember
caches the initial state and will hold it forever unless you supply a key that you think might change and will let remember
re-calculate a new initial state to be remembered, in my case I supplied the key as the todo object itself and when remember
sees the same object reference but with a different value, it will re-calculate
.
Having this understanding now, I can't imagine a way when there is no layer that will hold an object (remember
) and prevent unnecessary re-composition when the state of an object changes.
Just sharing what I learned, also open for discussion that I may have said in a wrongful way.