使用组合导航导航时惰性列闪烁
Lazy Column is blinking when navigating with compose navigation
我设置了导航、分页并使用流连接 ui 与模型。如果简化的话,我的屏幕代码是这样的:
@Composable
MainScreen() {
val listState = rememberLazyListState()
val lazyItems = Pager(PagingConfig(...)) { ... }
.flow
.cachedIn(viewModelScope)
.collectAsLazyPagingItems()
LazyColumn(state = listState) {
items(lazyItems, key = { it.id }) { ... }
}
}
这是我的 NavHost 代码:
NavHost(navController, startDestination = "mainScreen") {
composable("mainScreen") {
MainScreen()
}
}
但是当我从另一个屏幕导航回 MainScreen 或只是打开抽屉时,数据再次从 DataSource 加载,我看到明显的闪烁 LazyColumn
。
如何避免重新加载数据?
您的代码为我提供了 cachedIn
的以下错误:
Flow operator functions should not be invoked within composition
您不应忽略此类警告。
在转换期间,Compose Navigation 会多次重新组合消失和出现的视图。这是预期的行为。
并且您的代码创建了一个新的 Pager
,每次重组时都有一个新的流程,这就是导致问题的原因。
解决它的最简单方法是使用remember
:它会在重组之间缓存寻呼机流:
val lazyItems = remember {
Pager(PagingConfig(/* ... */)) { /* ... */ }
.flow
.cachedIn(viewModelScope)
.collectAsLazyPagingItems()
}
但是在配置更改期间它仍然会被重置,例如设备旋转。防止这种情况的最佳方法是将此逻辑移动到视图模型中:
class MainScreenViewModel : ViewModel() {
val pagingFlow = Pager(PagingConfig(/* ... */)) { /* ... */ }
.flow
.cachedIn(viewModelScope)
}
@Composable
fun MainScreen(
viewModel = viewModel<MainScreenViewModel>()
) {
val lazyItems = viewModel.pagingFlow.collectAsLazyPagingItems()
}
我设置了导航、分页并使用流连接 ui 与模型。如果简化的话,我的屏幕代码是这样的:
@Composable
MainScreen() {
val listState = rememberLazyListState()
val lazyItems = Pager(PagingConfig(...)) { ... }
.flow
.cachedIn(viewModelScope)
.collectAsLazyPagingItems()
LazyColumn(state = listState) {
items(lazyItems, key = { it.id }) { ... }
}
}
这是我的 NavHost 代码:
NavHost(navController, startDestination = "mainScreen") {
composable("mainScreen") {
MainScreen()
}
}
但是当我从另一个屏幕导航回 MainScreen 或只是打开抽屉时,数据再次从 DataSource 加载,我看到明显的闪烁 LazyColumn
。
如何避免重新加载数据?
您的代码为我提供了 cachedIn
的以下错误:
Flow operator functions should not be invoked within composition
您不应忽略此类警告。
在转换期间,Compose Navigation 会多次重新组合消失和出现的视图。这是预期的行为。
并且您的代码创建了一个新的 Pager
,每次重组时都有一个新的流程,这就是导致问题的原因。
解决它的最简单方法是使用remember
:它会在重组之间缓存寻呼机流:
val lazyItems = remember {
Pager(PagingConfig(/* ... */)) { /* ... */ }
.flow
.cachedIn(viewModelScope)
.collectAsLazyPagingItems()
}
但是在配置更改期间它仍然会被重置,例如设备旋转。防止这种情况的最佳方法是将此逻辑移动到视图模型中:
class MainScreenViewModel : ViewModel() {
val pagingFlow = Pager(PagingConfig(/* ... */)) { /* ... */ }
.flow
.cachedIn(viewModelScope)
}
@Composable
fun MainScreen(
viewModel = viewModel<MainScreenViewModel>()
) {
val lazyItems = viewModel.pagingFlow.collectAsLazyPagingItems()
}