如何优化 JetPack Compose 列表性能?
How optimize JetPack Compose list performance?
我有一个简单的可组合函数,其中包含 LazyColumn:
@Composable
fun MyScreen(itemList: List<Item>) {
LazyColumn {
intems(itemList) {
...
}
}
}
一切正常,但当滚动到达某个位置索引时,我的 ViewState(itemList
) 应该会改变。这就是为什么我将以下行添加到我的可组合函数中:
@Composable
fun MyScreen(itemList: List<Item>) {
val lazyListState = rememberLazyListState()
viewModel.onPositionChanged(lazyListState.firstVisibleItemIndex)
LazyColumn(state = lazyListState) {
intems(itemList) {
...
}
}
}
一切如我所料,但性能明显下降。我该如何解决?
你这里有两个问题:
- 您正在使用
lazyListState.firstVisibleItemIndex
直接读取可组合项中的状态,这会导致继续重组 - 每次 lazyListState
的任何部分发生变化时,例如在每个滚动像素上。
- 您正在直接从可组合项进行
viewModel.onPositionChanged
调用。建议从特殊的副作用函数进行此类调用,阅读 thinking in compose and side effects documentation. 中有关该主题的更多信息
在这种情况下 LaunchedEffect
和 snapshotFlow
可以像这样使用:
LaunchedEffect(Unit) {
snapshotFlow { lazyListState.firstVisibleItemIndex }
.collect(viewModel::onPositionChanged)
}
当您需要根据列表状态更新视图时,您也可能遇到同样的问题。在这种情况下应该使用derivedStateOf
:只有当计算值实际改变时才会导致重组。
val firstVisibleItemIndex by remember {
derivedStateOf {
lazyListState.firstVisibleItemIndex
}
}
我有一个简单的可组合函数,其中包含 LazyColumn:
@Composable
fun MyScreen(itemList: List<Item>) {
LazyColumn {
intems(itemList) {
...
}
}
}
一切正常,但当滚动到达某个位置索引时,我的 ViewState(itemList
) 应该会改变。这就是为什么我将以下行添加到我的可组合函数中:
@Composable
fun MyScreen(itemList: List<Item>) {
val lazyListState = rememberLazyListState()
viewModel.onPositionChanged(lazyListState.firstVisibleItemIndex)
LazyColumn(state = lazyListState) {
intems(itemList) {
...
}
}
}
一切如我所料,但性能明显下降。我该如何解决?
你这里有两个问题:
- 您正在使用
lazyListState.firstVisibleItemIndex
直接读取可组合项中的状态,这会导致继续重组 - 每次lazyListState
的任何部分发生变化时,例如在每个滚动像素上。 - 您正在直接从可组合项进行
viewModel.onPositionChanged
调用。建议从特殊的副作用函数进行此类调用,阅读 thinking in compose and side effects documentation. 中有关该主题的更多信息
在这种情况下 LaunchedEffect
和 snapshotFlow
可以像这样使用:
LaunchedEffect(Unit) {
snapshotFlow { lazyListState.firstVisibleItemIndex }
.collect(viewModel::onPositionChanged)
}
当您需要根据列表状态更新视图时,您也可能遇到同样的问题。在这种情况下应该使用derivedStateOf
:只有当计算值实际改变时才会导致重组。
val firstVisibleItemIndex by remember {
derivedStateOf {
lazyListState.firstVisibleItemIndex
}
}