I have a scenario where I add item(s) to a SnapshotStateList<T>
inside the ViewModel
. This list of items gets displayed using a LazyColumn
in the UI.
This is my ViewModel class
class MainViewModel(application: Application) : AndroidViewModel(application) {
val data = mutableStateListOf<String>()
init {
viewModelScope.launch { loadData() }
}
private suspend fun loadData() {
// I am adding items after a delay to simulate
// items getting added from a flow/other sources
delay(2000L)
data.add(sampleText(1))
delay(2000L)
data.add(sampleText(2))
delay(2000L)
data.add(sampleText(3))
delay(2000L)
data.add(sampleText(4))
delay(2000L)
data.add(sampleText(5))
}
private fun sampleText(id: Int): String = "Sample Text $id"
}
The UI consists of a single LazyColumn
Composable.
@Composable
fun HomeScreen(viewModel: MainViewModel = viewModel()) {
TextList(textItems = viewModel.data)
}
@Composable
fun TextList(textItems: List<String>) {
LazyColumn {
items(textItems, key = { it.hashCode() }) {
println("TextList: Composing Text = $it")
Text(text = it)
}
}
}
I expect to see the println()
line for each item as they get added to the list. However, this is what I see in the logs:
2023-08-12 21:55:30.352 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:30.895 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:30.905 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:32.899 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:32.902 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:32.912 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:34.918 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:34.921 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:34.923 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:34.931 29930-29930 System.out I TextList: Composing Text = Sample Text 4
2023-08-12 21:55:36.919 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:36.922 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:36.925 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:36.931 29930-29930 System.out I TextList: Composing Text = Sample Text 4
2023-08-12 21:55:36.943 29930-29930 System.out I TextList: Composing Text = Sample Text 5
I am confused as to why all the previously added items get's re-composed every time a new item is added to the list?
This seems related to Jetpack Compose lazy column all items recomposes when a single item update, but the solution didn't help here.
Edit #1:
As suggested by CommonsWare, I did flatten out the UI and moving the TextList
but the results don't change
@Composable
fun HomeScreen(viewModel: MainViewModel = viewModel()) {
LazyColumn {
items(viewModel.data, key = { it.hashCode() }) {
println("TextList: Composing Text = $it")
Text(text = it)
}
}
}