使用组合导航导航时惰性列闪烁

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()
}