使用StateFlow存储UI状态时返回Fragment如何恢复视图状态?
问题根因
原有写法的核心问题是状态收集器和Fragment实例生命周期绑定,而非Fragment视图生命周期绑定:
lifecycleScope是Fragment实例的生命周期作用域,只要Fragment实例没有被销毁(回退栈中的Fragment仅销毁视图、不会销毁实例),该作用域就一直存活- 首次启动收集后,StateFlow的当前值已经被旧收集器消费,在StateFlow无新值更新的情况下,后续视图重建时旧收集器不会再重复下发相同值,导致新视图只能拿到初始状态
解决方案
方案1:绑定视图生命周期收集状态(推荐)
将状态收集的时机放到onViewCreated中,使用和视图生命周期绑定的viewLifecycleOwner.lifecycleScope启动收集,配合官方推荐的repeatOnLifecycleAPI实现更安全的收集逻辑:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewLifecycleOwner.lifecycleScope.launch { // 仅在视图处于STARTED及以上状态时收集,视图销毁自动取消收集 viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.uiState.collect { // 按状态更新UI } } } }
该方案的逻辑是:每次Fragment从回退栈返回、重建视图时,都会生成新的viewLifecycleOwner,并注册新的StateFlow收集器,StateFlow的粘性特性会自动把最新的当前值发送给新收集器,直接完成视图状态恢复。
方案2:使用扩展方法简化写法
如果使用AndroidX lifecycle 2.6.0及以上版本,可以直接用collectWithLifecycle扩展方法简化代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.uiState.collectWithLifecycle( lifecycleOwner = viewLifecycleOwner, minActiveState = Lifecycle.State.STARTED ) { uiState -> // 更新UI } }
内容的提问来源于stack exchange,提问作者Karol Kulbaka
相关产品推荐
相关产品推荐

