从列表中删除后保留在内存中的 LazyColumn 项
LazyColumn items staying in memory after they are removed from the list
我发现我的应用程序使用了异常大量的内存。有一个 LazyColumn
定期更新数据。我发现在这些更新之后,内存中的列表项实例的数量随着时间的推移而增加,并且变得明显大于列表中的最大项目数量。
我做了一个小样本来说明这个问题here。
这些是数据项:
@Immutable
data class TestDataBlock(
val id: String,
val data: Int
)
LazyColumn 看起来像这样。
@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}")
}
在这个示例中,我在 LazyColumn
中设置了两部分数据,然后我清理了它。
@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)
}
我希望没有在内存中引用项目的示例(在探查器中可见),但不幸的是,最后一组数据仍在内存中,从 Compose 的某处引用。
在项目包含 LazyRows
和图像的真实应用程序中,此类多次更新会导致内存阻塞,并可能导致 OOM。
项目 类 是不可变的 (@Immutable
),并且所有项目都有唯一的 ID。
对于这种行为的原因以及是否可以更改,我将不胜感激。
您正在从 MutableList 而不是从 Flow 中检索您的值。可变列表会重新排列所有项目,而流程将仅检索可见项目以及在第一个可见项目之前或最后一个可见项目之后的多个项目。您应该使用带有 Flow 的分页库来填充您的 LazyList。您可以阅读以下文章,了解如何使用 Compose 和 LazyColum 进行分页:
我已经为 Google 填写了他们复制的错误:https://issuetracker.google.com/issues/207946467
我发现我的应用程序使用了异常大量的内存。有一个 LazyColumn
定期更新数据。我发现在这些更新之后,内存中的列表项实例的数量随着时间的推移而增加,并且变得明显大于列表中的最大项目数量。
我做了一个小样本来说明这个问题here。
这些是数据项:
@Immutable
data class TestDataBlock(
val id: String,
val data: Int
)
LazyColumn 看起来像这样。
@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}")
}
在这个示例中,我在 LazyColumn
中设置了两部分数据,然后我清理了它。
@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)
}
我希望没有在内存中引用项目的示例(在探查器中可见),但不幸的是,最后一组数据仍在内存中,从 Compose 的某处引用。
在项目包含 LazyRows
和图像的真实应用程序中,此类多次更新会导致内存阻塞,并可能导致 OOM。
项目 类 是不可变的 (@Immutable
),并且所有项目都有唯一的 ID。
对于这种行为的原因以及是否可以更改,我将不胜感激。
您正在从 MutableList 而不是从 Flow 中检索您的值。可变列表会重新排列所有项目,而流程将仅检索可见项目以及在第一个可见项目之前或最后一个可见项目之后的多个项目。您应该使用带有 Flow 的分页库来填充您的 LazyList。您可以阅读以下文章,了解如何使用 Compose 和 LazyColum 进行分页:
我已经为 Google 填写了他们复制的错误:https://issuetracker.google.com/issues/207946467