I built a lazy column that gets it`s data from ViewModel and every time I add an item the lazy column recomposes and the new Item is being viewed in the lazy column, But when I added the functionality of deleting an Item the lazy column does not recompose and the removed item stays on the screen until a configuration change happens (Like rotating the screen).
My question is how to make the lazy column know that the list has been updated after each Delete operation.
here is the ViewModel:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.shoppinglistcompose.entities.Item
class AddNewShoppingListViewModel : ViewModel() {
val items = MutableLiveData<MutableList<Item>>(mutableListOf())
fun addNewItem(newItem: Item) {
items.value = items.value?.plus(listOf(newItem)) as MutableList<Item>?
}
fun removeItem(item: Item) {
items.value!!.remove(item)
items.value = items.value?.plus(listOf()) as MutableList<Item>?
}
}
,The Compsable that shows the Lazy Column:
content = { paddingValues ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
) {
OutlinedTextField(
value = text,
onValueChange = { textFieldsViewModel.onShoppingListNameChanged(it) },
label = { Text(text = "Shopping list Name") },
modifier = Modifier
.fillMaxWidth()
.padding(start = 30.dp, end = 30.dp, bottom = 8.dp)
)
if (!items.value?.isEmpty()!!) {
LazyColumn(
Modifier
.animateContentSize()
.fillMaxSize()
.padding(paddingValues)
) {
items(items = items.value!!) {
SingleItem(item = it) {
addNewShoppingListViewModel.removeItem(it)
}
}
}
} else {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = "There are no shopping Items",
color = Color.Red,
style = MaterialTheme.typography.h5
)
}
}
}
if (showDialog.value) {
MyDialog(
showDialog = showDialog,
textFieldsViewModel = textFieldsViewModel,
) {
val name = textFieldsViewModel.shoppingItemText.value
val quantity = textFieldsViewModel.itemQuantityText.value
val item = Item(0, name!!, quantity!!.toInt(), 0)
addNewShoppingListViewModel.addNewItem(item)
textFieldsViewModel.shoppingItemText.value = ""
textFieldsViewModel.itemQuantityText.value = ""
showDialog.value = !showDialog.value
}
}
},
And here is the Composable fun of the Item it self:
@Composable
fun SingleItem(item: Item, deleteClick: () -> Unit) {
val composableScope = rememberCoroutineScope()
val new: MutableState<Boolean> = remember {
mutableStateOf(true)
}
val color = remember { Animatable(Color(0xFFB9F6CA)) }
LaunchedEffect(new.value) {
color.animateTo(if (new.value) Color(0xFFB9F6CA) else Color(0xFFE0F2F1))
}
Card(
modifier = Modifier
.padding(4.dp)
.fillMaxWidth(),
shape = RoundedCornerShape(8.dp),
backgroundColor = color.value,
elevation = 3.dp
) {
composableScope.launch {
delay(2000)
new.value = false
}
Row(modifier = Modifier.fillMaxWidth() , horizontalArrangement = Arrangement.SpaceBetween) {
Column(
modifier = Modifier,
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.SpaceBetween
) {
Text(text = item.name, style = MaterialTheme.typography.h5)
Text(text = "${item.quantity}", style = MaterialTheme.typography.h6)
}
IconButton(onClick = deleteClick) {
Icon(Icons.Rounded.Delete, "Button for deleting an Item of the items list.")
}
}
}
}