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

Activity重建时Fragment无法获取Activity创建的带参ViewModel

解决Activity重建后Fragment无法获取带参ViewModel的问题

咱们先把问题根源捋清楚:
当Activity因为系统语言切换、权限变更这类配置变更重建时,之前的代码逻辑会出状况——首次启动时Fragment能拿到ViewModel,是因为Activity已经用Factory创建好了实例,系统直接复用;但重建后,新的Activity实例如果没正确用Factory初始化ViewModel,或者Fragment获取时没指定Factory,系统会尝试调用MessageViewModel的无参构造,可你的ViewModel只有带参构造,自然就报无法实例化的错误了。

一步步解决方案

1. 先确认你的Factory实现没问题

首先得保证MessageVMFactory能正确创建MessageViewModel,示例代码如下:

class MessageVMFactory : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MessageViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return MessageViewModel(MutableLiveData()) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

2. Activity重建时必须用Factory获取ViewModel

在Activity的onCreate方法里,不管是不是重建场景,都要通过指定Factory来获取ViewModel,不能省略Factory参数:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // 不管是首次启动还是重建,都用Factory获取ViewModel
    val viewModel = ViewModelProviders.of(this, MessageVMFactory())
        .get(MessageViewModel::class.java)
}

3. Fragment获取ViewModel时也要指定Factory

Fragment里不能只传activity就完事,必须同时带上Factory,这样才能确保拿到的是Activity层级的正确ViewModel实例:

// 在Fragment的onViewCreated或者onActivityCreated方法中
val viewModel = ViewModelProviders.of(requireActivity(), MessageVMFactory())
    .get(MessageViewModel::class.java)

额外说明

可能你会好奇为啥首次启动没问题?因为首次启动时Activity先通过Factory创建了ViewModel,Fragment去获取时系统直接返回已存在的实例,不需要调用构造函数;但重建时原ViewModel的状态没法自动恢复(因为带参构造需要Factory来初始化),这时候没指定Factory的话,系统就不知道怎么创建新实例,所以报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:33:48