Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using List as State, how to update UI when item`attribute change in Jetpack Compose?

For example, I load data into a List, it`s wrapped by MutableStateFlow, and I collect these as State in UI Component.

The trouble is, when I change an item in the MutableStateFlow<List>, such as modifying attribute, but don`t add or delete, the UI will not change.

So how can I change the UI when I modify an item of the MutableStateFlow?

These are codes:

ViewModel:

data class TestBean(val id: Int, var name: String)
class VM: ViewModel() {
    val testList = MutableStateFlow<List<TestBean>>(emptyList())

    fun createTestData() {
        val result = mutableListOf<TestBean>()
        (0 .. 10).forEach {
            result.add(TestBean(it, it.toString()))
        }
        testList.value = result
    }

    fun changeTestData(index: Int) {

        // first way to change data
        testList.value[index].name = System.currentTimeMillis().toString()

        // second way to change data
        val p = testList.value[index]
        p.name = System.currentTimeMillis().toString()
        val tmplist = testList.value.toMutableList()
        tmplist[index].name = p.name
        testList.update { tmplist }
}

}

UI:

    setContent {
        LaunchedEffect(key1 = Unit) {
            vm.createTestData()
        }
        Column {
            vm.testList.collectAsState().value.forEachIndexed { index, it ->
                Text(text = it.name, modifier = Modifier.padding(16.dp).clickable {
                    vm.changeTestData(index)
                    Log.d("TAG", "click: ${index}")
                })
            }
        }
    }
like image 534
Li Zhenxin Avatar asked Sep 17 '25 20:09

Li Zhenxin


1 Answers

Both Flow and Compose mutable state cannot track changes made inside of containing objects.

But you can replace an object with an updated object. data class is a nice tool to be used, which will provide you all copy out of the box, but you should emit using var and only use val for your fields to avoid mistakes.

Check out Why is immutability important in functional programming?

testList.value[index] = testList.value[index].copy(name = System.currentTimeMillis().toString())
like image 105
Philip Dukhov Avatar answered Sep 19 '25 10:09

Philip Dukhov