You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 10:50:33