'How to Update List State to show updates in Compose

I'm trying to have a list that updates on the fly, it may change a few fields or many. The initial update at updateItems() is fine, everything displays as it should, however consecutive updates at updateOneItem are ignored by Jetpack Compose.

// ****ViewModel code
val _itemList: MutableStateFlow<List<Item>> = MutableStateFlow(emptyList())

fun updateItems() {
    viewModelScope.launch {
        _itemList.value = itemRepository.getItems()
    }
}

fun updateOneItem(newVal:Int){
    _itemList.value[_itemList.value.indexOf(item)].weight = newVal
    //this is where I cannot have an update show up in compose no matter what
    _itemList.tryEmit(_itemList.value)
}
// ****continued ViewModel Code

I've been trying to copy the list, also tried mutableStateListOf but so far nothing works.



Solution 1:[1]

Flow can't know when some mutable property of the containing object changes. When you try to emit it, it checks the address of the object - it's the same as it was - and ignores that emit.

You can force it by creating a copy of the list.

But the cleanest way is using mutableStateListOf and making your item an immutable data class, then you can easily update it by creating a copy. Check out Why is immutability important in functional programming?

It can look like this:

data class Item(val weight: Int)

private val _itemList = mutableStateListOf<Item>()
val itemList: List<Item> = _itemList

fun updateItems() {
    viewModelScope.launch {
        _itemList.addAll(itemRepository.getItems())
    }
}

fun updateOneItem(newVal:Int){
    val index = _itemList.indexOf(item)
    _itemList[index] = _itemList[index].copy(weight = newVal)
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pylyp Dukhov