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

Jetpack Compose Wear OS:ViewPager2中PositionIndicator状态丢失问题

问题分析与解决方案

问题根源

ViewPager2默认会回收超出预加载范围的Fragment(销毁其视图),当切换回Compose Fragment时,Fragment的onCreateView会重新执行,此时通过rememberScalingLazyListState()创建的状态实例是全新的——虽然列表数据仍可正常滚动,但PositionIndicator绑定的是新的状态实例,无法监听原有列表的滚动变化,导致滑块不再跟随滚动。设置setOffscreenPageLimit(4)能解决问题,是因为所有Fragment都被保留在内存中,状态没有被销毁,但这种方式会占用过多资源,不适合智能手表设备。

解决方案1:用ViewModel保存列表状态(推荐)

将ScalingLazyListState的生命周期与Fragment的ViewModel绑定,ViewModel不会随Fragment视图的销毁而被回收,确保切换Fragment后状态得以复用:

  1. 创建ViewModel:
class ComposeListViewModel : ViewModel() {
    // 全局唯一的列表状态实例
    val listState = ScalingLazyListState()
}
  1. 在Compose Fragment中使用ViewModel:
class ComposeFragment : Fragment() {
    private val viewModel by viewModels<ComposeListViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return ComposeView(requireContext()).apply {
            setContent {
                MaterialTheme {
                    Column {
                        PositionIndicator(
                            scalingLazyListState = viewModel.listState
                        )
                        ScalingLazyColumn(
                            state = viewModel.listState,
                            // 列表配置
                        ) {
                            // 填充列表项
                            items(50) { index ->
                                Text(text = "Item $index", modifier = Modifier.padding(16.dp))
                            }
                        }
                    }
                }
            }
        }
    }
}

解决方案2:用rememberSaveable持久化状态

如果不想使用ViewModel,可以通过自定义rememberSaveable来保存状态(需要处理状态的序列化):

@Composable
fun rememberSavedScalingLazyListState(): ScalingLazyListState {
    return rememberSaveable(
        saver = ScalingLazyListState.Saver
    ) {
        ScalingLazyListState()
    }
}

然后在Compose代码中替换原有的rememberScalingLazyListState():

setContent {
    MaterialTheme {
        val listState = rememberSavedScalingLazyListState()
        Column {
            PositionIndicator(scalingLazyListState = listState)
            ScalingLazyColumn(state = listState) {
                // 列表项
            }
        }
    }
}

这种方式会在Fragment视图销毁时序列化状态,重建时反序列化恢复,适合轻量状态场景,但相比ViewModel,序列化会带来额外性能开销,智能手表设备优先推荐第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 09:02:27