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

Fragment中ViewModel屏幕旋转丢失数据,求排查原因

问题分析与解决方案

看起来你遇到的核心问题是ViewModel在屏幕旋转时被意外重新创建了,导致uiModel被重置为null——这和ViewModel本该在配置变化时保留数据的特性不符,咱们一步步拆解原因和解决办法:

最可能的原因

你代码里的ViewModel绑定的是Fragment的生命周期,但如果你的Activity在onCreate方法中每次都创建新的DiaryFragment实例(比如直接new DiaryFragment()并替换容器),那么当屏幕旋转触发Activity重建时,新的Fragment实例会拥有全新的ViewModelStore,导致ViewModel被重新初始化,uiModel自然就变回null了。

另外,你使用的ViewModelProviders.of(this)是较旧的API,虽然不是直接原因,但也可能带来一些潜在问题,推荐替换为最新的ViewModelProvider。

修复步骤

1. 修正Activity中Fragment的创建逻辑

在Activity的onCreate里,只有当savedInstanceState为null时(也就是首次启动Activity)才创建新的Fragment,否则让FragmentManager自动恢复之前的Fragment实例:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // 仅在首次启动时创建Fragment
    if (savedInstanceState == null) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, DiaryFragment())
            .commit()
    }
}

这样屏幕旋转时,Fragment会被系统自动恢复,它绑定的ViewModel也会被保留,uiModel就不会被重置了。

2. 替换为最新的ViewModelProvider API

把Fragment中初始化ViewModel的代码替换为:

// 替换旧的 ViewModelProviders.of(this).get(...)
viewModel = ViewModelProvider(this).get(DiaryViewModel::class.java)

这个新API更简洁,也避免了旧API的一些潜在问题。

3. 优化ViewModel的初始化逻辑

用lazy委托来初始化uiModel,可以避免手动判断null的麻烦,确保它只会被初始化一次:

class DiaryViewModel: ViewModel() {
    private val uiModel: MutableLiveData<DiaryUIModel> by lazy {
        MutableLiveData<DiaryUIModel>().apply {
            value = DiaryUIModel()
        }
    }

    fun getModel(): LiveData<DiaryUIModel> = uiModel
}

为什么这样能解决问题?

当屏幕旋转时,Activity会重建,但savedInstanceState不为null,所以不会创建新的Fragment。FragmentManager会恢复之前的Fragment实例,而该Fragment的ViewModelStore会被保留,ViewModel也就不会被重新创建,uiModel里的数据自然就保留下来了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:44:41