I found out that my app uses an unusually large amount of memory. There's a LazyColumn
where data is updated regularly. I found out that after these updates the amount of list item instances in memory increases with time and grows to become significantly larger than the maximum amount of items in the list at once.
I made a small sample illustrating the problem here.
These are data items:
@Immutable
data class TestDataBlock(
val id: String,
val data: Int
)
The LazyColumn looks like this.
@Composable
fun List(dataItems: List<TestDataBlock>) {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
itemsIndexed(items = dataItems,
key = { index, item ->
item.id
}
) { rowIndex, rowItem ->
drawElement(rowItem)
}
}
}
@Composable
fun drawElement(rowItem: TestDataBlock) {
Text(text = "${rowItem.data}")
}
In this sample, I set two portions of data in LazyColumn
and after that, I clean it up.
@Composable
fun runTest() {
var itemsState: MutableState<List<TestDataBlock>> = remember {
mutableStateOf(listOf())
}
LaunchedEffect(Unit) {
delay(1000)
itemsState.value = MutableList<TestDataBlock>(30) { rowIndex ->
TestDataBlock(id = rowIndex.toString(), data = 1)
}
delay(1000)
itemsState.value = MutableList<TestDataBlock>(30) { rowIndex ->
TestDataBlock(id = rowIndex.toString(), data = 2)
}
delay(1000)
itemsState.value = listOf()
}
List(dataItems = itemsState.value)
}
I would expect no examples of items with references in memory (visible in profiler), but unfortunately, the last set of data is still in memory, referenced somewhere from Compose.
In the real app where items contain LazyRows
and images such multiple updates lead to clogging up memory and potentially, to OOM.
The item classes are immutable (@Immutable
), and all items have unique ids.
I would be grateful for any ideas about the reasons of this behaviour and if it can be changed.