0

I am using LazyColumn to represent a list of names containing an Index, and its data source is a StateFlow<List<IndexName>>.

I find that if I add elements to this MutableStateFlow list, the interface is updated immediately. But if I modify the elements in this MutableStateFlow and then update the whole list to a new list, the interface does not refresh. Why?

Codes:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            UpdateListTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting(Container())
                }
            }
        }
    }
}

class IndexName(val index: Int, var name: String)

class Container {
    private var _names = MutableStateFlow<List<IndexName>>(listOf())
    val names: StateFlow<List<IndexName>> = _names

    fun insert(value: String) {
        val index = _names.value.size
        _names.value = _names.value + IndexName(index, value)
    }

    fun update(name: String) {
        val tmp = _names.value.toList()
        tmp.forEach {
            it.name = name
        }
        _names.value = tmp
    }
}

@Composable
fun Greeting(container: Container) {
    val names = container.names.collectAsState().value

    Column {
        Row {
            Button(onClick = {
               container.insert((System.currentTimeMillis()/1000L).toString())
            }) {
                Text(text = "insert")
            }
            Button(onClick = {
                container.update((System.currentTimeMillis()/1000L).toString())
            }) {
                Text(text = "update")
            }
        }
        LazyColumn {
            items(names) { item ->
                key(item.index) {
                    Text(item.name)
                }
            }
        }
    }
}
progquester
  • 1,228
  • 14
  • 23

1 Answers1

1

The issue is with this code, it does not update the value.

tmp.forEach {
    it.name = name
}

Solution

  1. Make IndexName a data class. (Or manually add a method for copy if data class can not be used).
  2. Change update()
fun update(name: String) {
    val tmp = _names.value.toList().map {
        it.copy(
            name = name,
        )
    }
    _names.value = tmp
}
Abhimanyu
  • 11,351
  • 7
  • 51
  • 121