Compose中LazyColumn结合Paging3更新Item后列表自动滚顶问题
问题:分页列表更新后返回自动滚动到顶部
我在Composable界面中使用Paging3结合RemoteMediator获取远程数据,并将其存储在Room数据库中进行展示。点击列表项会打开详情页,在详情页可以更新该列表项在数据库中的数据。由于分页数据是以Flow形式收集的,列表会自动更新。
但遇到一个问题:每当在详情页完成数据更新后,返回列表界面时,列表会直接跳转到顶部(无滚动动画),看起来像是整个列表被重新加载,而非仅更新对应项。
界面代码
@OptIn(ExperimentalMaterial3Api::class) @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun ReposListScreen(navController: NavController, viewModel: RepositoriesViewModel = hiltViewModel()) { val repos = viewModel.data.collectAsLazyPagingItems() val snackBarHostState = remember { SnackbarHostState() } val coroutineScope = rememberCoroutineScope() Scaffold( topBar = { TopAppBar( title = { Text(text = stringResource(id = R.string.str_best_rated_repos)) } ) }, snackbarHost = { SnackbarHost(snackBarHostState) }, bottomBar = { BottomNavigationBarComponent() { coroutineScope.launch { snackBarHostState.showSnackbar("You pressed $it.") } } } ) { LazyColumn( modifier = Modifier.padding(paddingValues = it) ) { when (val appendState = repos.loadState.append) { is LoadState.Loading -> { item { LoadingNextPageItem(modifier = Modifier.fillMaxWidth()) } } is LoadState.Error -> { item { ErrorMessage( modifier = Modifier .fillMaxWidth(), message = appendState.error.localizedMessage.orEmpty(), onClickRetry = { repos.retry() } ) } } else -> {} } items(count = repos.itemCount, key = repos.itemKey { it.id }) { index -> repos[index]?.let { repo -> RepoItem( repo, onRepoClicked = { navController.navigate(Routes.RepoDetailScreen.createRoute(repo.id)) } ) } } item { Spacer(modifier = Modifier.padding(4.dp)) } } }
ViewModel代码
@HiltViewModel class RepositoriesViewModel @Inject constructor( private val getPagedBestRatedReposUseCase: GetPagedBestRatedReposUseCase ) : ViewModel() { private var _state: MutableStateFlow<UiState> = MutableStateFlow(UiState(loading = true)) val state: StateFlow<UiState> = _state.asStateFlow() private var _data: MutableStateFlow<PagingData<Repository>> = MutableStateFlow(PagingData.empty()) val data: StateFlow<PagingData<Repository>> = _data.asStateFlow() init { viewModelScope.launch(Dispatchers.IO) { _state.value = UiState(loading = true) getPagedBestRatedReposUseCase() .cachedIn(viewModelScope) .catch { _state.update { it.copy(error = true, loading = false) } } .collect { repos -> _state.update { it.copy( dataSource = repos, loading = false, error = false ) } _data.update { repos } } } }
解决方案
问题根源在于val repos = viewModel.data.collectAsLazyPagingItems()的调用位置错误——之前是在NavHost内部的Composable界面中调用的,正确的做法是将这行代码移到NavHost初始化之前调用。
感谢@BenjyTec的评论指引找到相关问题线索。
内容的提问来源于stack exchange,提问作者alGhul7
相关产品推荐
相关产品推荐

