Reputation: 343
I'm creating an app that, among other things, enables the user to add a Consumer, and then remove him later. The consumers are shown in cards with a remove button in the end.
Adding a consumer works fine. However, when I try to remove a consumer, the one removed in the app screen is always the last one. I know this is not a logic implementation mistake, because I stopped the Debugger right before the items()
call, and in any recomposition the list holding the consumers has the correct consumer removed! The following image shows the result after clicking the Remove button from the "B" card (the card removed is "C"!):
Look what the debugger shows right before the recomposition takes place:
The relevant code is below.
The ViewModel and Model (relevant part) definitions:
class ConsumidoresViewModel : ViewModel() {
var lista = mutableStateListOf<Consumidor>()
fun add(consumidor: Consumidor){
lista += consumidor
}
fun remove(consumidor: Consumidor){
lista.remove(consumidor)
}
}
data class Consumidor(var nome: String)
...
The main composable, called directly from .onCreate():
fun UsersView() {
var consumidores: ConsumidoresViewModel = viewModel()
...
LazyColumn() {
items(items = consumidores.lista) { consumidor ->
CardNome(consumidor, consumidores)
}
}
The fucntion call of the Remove button:
IconButton(onClick = { consumidorViewModel.remove(consumidor) }) { ... }
I can't figure out what I'm doing wrong. I'm fairily new with Android Programming / Compose, but I have been programming for decades (not professionaly). Can someone point me to a direction? It probably has something to do with my Sates / View Model implementation, but I can't find out what, as the SnapshotStateList
on the debugger clearly shows "A" and "C" cards present, and "B" gone!
Upvotes: 4
Views: 841
Reputation: 6257
Based on the official docs.
By default, each item's state is keyed against the position of the item in the list or grid. However, this can cause issues if the data set changes, since items which change position effectively lose any remembered state. If you imagine the scenario of LazyRow within a LazyColumn, if the row changes item position, the user would then lose their scroll position within the row.
So it's usually a good set up when your data class has a unique property like an id
if you plan to manipulate a collection of it (like your removal operation), you can then use it as a key = {...}
for the LazyColumn
so it knows not to use the index as a unique identifier for its item elements
, and that could be the reason why your'e having a wrong display of items after removing an element from the list.
LazyColumn() {
items(items = consumidorList, key = { it.id }) { consumidorItem ->
...
}
}
Update:
Linking my another answer for a movableContentOf{...}
sample.
Upvotes: 5