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

Jetpack Compose导航时如何保存LazyColumn的分页状态?

解决方案

最优实现方案(官方推荐,改造成本最低)

Pager、PagingSource都属于非Parcelable/序列化的复杂对象,无法通过rememberSaveable存入Bundle;同时放在Composable中用remember存储的状态会在导航跳转时随Composable移出Composition而销毁,返回后就会重新初始化拉取数据。
最简单的实现方案是将分页逻辑迁移到ViewModel中,利用ViewModel与导航目的地绑定的生命周期保留状态:

  1. 在对应页面的ViewModel中初始化Pager,并通过cachedIn绑定ViewModel作用域缓存分页数据
class SampleViewModel : ViewModel() {
    // 在此处初始化你的自定义PagingSource
    private val myPagingSource = MyCustomPagingSource()
    
    val pagingFlow = Pager(
        config = PagingConfig(pageSize = 25),
        initialKey = 0,
        pagingSourceFactory = { myPagingSource }
    ).flow
    // 核心:将分页数据缓存到ViewModel作用域,ViewModel不销毁则缓存不丢失
    .cachedIn(viewModelScope)
}
  1. 改造Composable代码,直接从ViewModel取分页流,不需要在Composable中创建Pager
@Composable
fun SampleScreen(
    composeNavController: NavHostController? = null,
    // 导航库会自动保留当前目的地对应的ViewModel实例,跳转不会销毁
    viewModel: SampleViewModel = viewModel()
) {
    val lazyPagingItems = viewModel.pagingFlow.collectAsLazyPagingItems()
    // rememberLazyListState内部默认实现了状态保存,数据存在时滚动位置自动恢复
    val listState = rememberLazyListState()

    LazyColumn(state = listState) {
        itemsIndexed(items = lazyPagingItems) { index, item ->
            MyRowItem(item) {
                composeNavController?.navigate(...)
            }
        }
    }
}

方案说明

  • 导航跳转时只要当前页面没有被从导航栈中pop移除,对应的ViewModel就不会被销毁,已经拉取的分页缓存、加载状态都会完整保留,返回页面时不需要重新请求后端接口
  • rememberLazyListState本身已支持状态持久化,只要分页数据存在,返回页面会自动恢复到之前的滚动位置,不需要额外处理

备选方案(不使用ViewModel的场景)

如果确实需要在Composable内部维护分页状态,可以自定义Saver分别保存分页的当前加载key、滚动位置的索引与偏移,返回页面时用保存的key作为Pager的initialKey初始化,再手动恢复滚动位置,该方案实现成本更高,非必要不推荐。

内容的提问来源于stack exchange,提问作者Damiancioo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:15:04