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

自定义ViewModel Factory每次返回新实例而非已有实例如何解决

问题原因分析
  • ViewModel 实例的存储和复用和你传入 ViewModelProvider 的第一个参数 ViewModelStoreOwner 直接绑定,每个独立的 ViewModelStoreOwner 都有专属的ViewModel缓存空间。你当前传入的是Fragment实例自身,如果每次展示Fragment时系统都会创建全新的Fragment实例(比如Navigation组件重复导航到同一目的地、手动调用事务remove后重新add Fragment),新的Fragment实例的缓存空间是空的,自然会触发Factory创建新的ViewModel实例。
  • 如果你是在配置变更(转屏、系统主题切换)的场景下出现该问题,说明你获取ViewModel的代码执行时机错误:如果逻辑放在了异步回调、onViewCreated之后的晚执行逻辑,或者你在Fragment中手动调用过clearViewModelStore之类的清理逻辑,也会导致缓存丢失触发新建。
  • 你提供的Factory代码存在笔误隐患:你声明的Application类型属性名为app,但创建ViewModel时传入的是application,如果实际运行时这个变量指向的不是Factory持有的Application实例,可能引发额外的异常导致缓存失效。
修复方案

场景1:仅需要在配置变更场景下复用ViewModel

将获取ViewModel的逻辑移动到Fragment的onCreate或者onCreateView的最顶部执行,同时修正Factory的笔误即可,修正后的代码如下:

// 修正后的自定义Factory
class MyViewModelFactory(
    private val app: Application,
    private val someClass: SomeClass,
) : ViewModelProvider.Factory {
    @Suppress("unchecked_cast")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            // 替换为实际持有的app属性
            return MyViewModel(app, someClass) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

// 获取ViewModel的代码放在onCreate/onCreateView顶部
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewModel = ViewModelProvider(this, MyViewModelFactory(requireActivity().application, someClass)).get(
        MyViewModel::class.java
    )
}

场景2:需要在多次创建的Fragment实例间复用ViewModel

修改ViewModelProvider的第一个参数,绑定到生命周期更长的ViewModelStoreOwner即可:

  • 如果需要在当前导航图范围内复用:传入 findNavController().getBackStackEntry(R.id.你的导航图ID).viewModelStoreOwner
  • 如果需要在整个Activity生命周期内复用:直接传入requireActivity()

示例代码如下:

// Activity级复用的示例
viewModel = ViewModelProvider(requireActivity(), MyViewModelFactory(requireActivity().application, someClass)).get(
    MyViewModel::class.java
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:15:09