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

使用Jetpack Compose Navigation导航后保留列表状态的最佳实践

导航返回后LazyColumn滚动状态保留实现方案

核心问题原因

你当前使用rememberLazyListState()创建列表状态,其内部基于remember实现,状态生命周期和列表页可组合项的组合周期绑定。导航到详情页时列表页会退出组合树,remember存储的状态被销毁,返回列表页时会重新初始化listState,所以滚动位置会重置到顶部。


优先实现方案(符合编码规范)

普通场景下优先使用rememberSaveable方案,该方案符合单一职责原则,UI相关状态存放在UI层,无需污染业务ViewModel,代码量极少。

LazyListState官方已经内置了序列化Saver,无需自己编写状态保存逻辑,直接修改列表状态初始化代码即可:

// 把原来的 val listState = rememberLazyListState() 替换为以下代码
val listState = rememberSaveable(saver = LazyListState.Saver) {
    LazyListState()
}

rememberSaveable的状态存储在组合树之外的SavedStateRegistry中,只要列表页还在导航回退栈中,状态就不会丢失,返回列表页时会自动恢复滚动位置,无需额外编写滚动逻辑。


备选方案:ViewModel存储(特殊场景使用)

如果你的需求需要支持APP被系统杀死重启后仍保留滚动位置,或者滚动位置需要和业务逻辑联动(比如上报用户浏览位置),可以使用ViewModel + SavedStateHandle的方案:

1. ViewModel层实现

class MainViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    // 通过SavedStateHandle存储,支持进程杀死后恢复
    private val _firstVisibleIndex = savedStateHandle.getStateFlow("list_first_index", 0)
    private val _firstVisibleOffset = savedStateHandle.getStateFlow("list_first_offset", 0)

    fun saveScrollState(index: Int, offset: Int) {
        savedStateHandle["list_first_index"] = index
        savedStateHandle["list_first_offset"] = offset
    }

    fun getScrollState(): Pair<Int, Int> {
        return _firstVisibleIndex.value to _firstVisibleOffset.value
    }
}

2. 列表页实现

val (initIndex, initOffset) = viewModel.getScrollState()
val listState = rememberLazyListState(
    initialFirstVisibleItemIndex = initIndex,
    initialFirstVisibleItemScrollOffset = initOffset
)

// 监听滚动变化实时保存到ViewModel
LaunchedEffect(listState) {
    snapshotFlow {
        listState.firstVisibleItemIndex to listState.firstVisibleItemScrollOffset
    }.collect { (index, offset) ->
        viewModel.saveScrollState(index, offset)
    }
}

选型建议

适用场景方案选择
仅需要导航返回保留滚动位置优先rememberSaveable方案
需要跨进程重启保留滚动位置、滚动位置关联业务逻辑选择ViewModel+SavedStateHandle方案

内容的提问来源于stack exchange,提问作者A.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 12:54:04