LazyColumn in jetpack compose does not recompose when list data changes, but forloop over data list works, I am not getting why and what is happening

689 views Asked by At

I am developing a app using jetpack compose, and I am new to this UI framework, I want to display the categories amountSpent property. I am changing the amount spend in dialog and want to reflect the change in list, Here issue is the Lazy Column does not recompose but Text inside categories forloop works. I am not sure why Lazy Column is not working but simple forloop is working

          var categories = remember {
            mutableStateListOf(
              Category.FoodCategory(amountSpent=100),
              Category.ShoppingCategory(amountSpent=50),
              Category.TransportationCategory(amountSpent=80),
              Category.EducationCategory(amountSpent=90)
            )
          }

categories[0].amountSpent=400
@Composable
fun HomeUi(categories: SnapshotStateList<Category>) {
         
LazyColumn() {
items(categories){
  Text(text = it.amountSpent.toString())
   }
}
categories.forEach{
  Text(text = it.amountSpent.toString())
}
}

I was expecting that Lazy Column and ForEach world result the same but to my shock Lazy Column did not work

The Output was
Before 
100
50
90
80
100
50
90
80

After Change
100
50
90
80
400
50
90
80

Code for category:

sealed class Category(
  val name: String,
  val totalBudget:Int,
  open var amountSpent: Int,
  @DrawableRes val icon : Int){
  data class FoodCategory(override var amountSpent: Int=0):
    Category("Food",500,amountSpent,R.drawable.ic_food)
  class ShoppingCategory(override var amountSpent: Int=0):
    Category("Shopping",500,0,R.drawable.ic_shopping)
  class TransportationCategory(override var amountSpent: Int=0):
    Category("Transportation",500,amountSpent,R.drawable.ic_transportation)
  class EducationCategory(override var amountSpent: Int=0):
    Category("Education",500,amountSpent,R.drawable.ic_education)

}

Edit Fixed the Issue: I had to remove the category form list and add it again so that the lazy column re-compiles, assigning value to it does not work,

Please can anyone explain if is this a bug from Jetpack compose or an issue from my side?

var categoryChanged = categories.find { cat == it.name }
                  categoryChanged?.amountSpent = categoryChanged?.amountSpent?.plus(400)!!
                  var ind = categories.indexOf(categoryChanged)
                  categories.remove(categoryChanged)
                  categories.add(ind, categoryChanged!!)

1

There are 1 answers

1
Dafi On

if you need a change item position or update value in list and you want to recomposition in LazyColumn, you have to add key.

LazyColumn {
    items(
        items = messages,
        key = { message ->
            // Return a stable + unique key for the item
            message.id
        }
    ) { message ->
        MessageRow(message)
    }
}