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

Android报错:无法创建ViewModel实例,带Context构造的ViewModel求助

解决ViewModel实例化报错:java.lang.RuntimeException: Cannot create an instance of class ViewModel

你碰到的这个问题核心有两个原因:

  1. ViewModel带参数的构造函数不被默认工厂支持:默认的ViewModelProvider.Factory只能创建无参构造的ViewModel实例,你的BooksFragmentViewModel有一个Context参数,所以默认工厂没办法完成实例化。
  2. 直接持有Context存在内存泄漏风险:ViewModel的生命周期通常比Fragment/Activity更长,如果持有组件级的Context,当组件被销毁时,ViewModel还可能存活,会导致Context无法被GC回收,引发内存泄漏。

下面给你两种可行的修复方案,优先推荐第二种更安全的实现:


方案一:自定义ViewModelFactory创建带参数的ViewModel

如果你确实需要传入Context,我们可以自定义一个ViewModel工厂类来处理带参数的实例化,但一定要传入Application Context来避免内存泄漏:

1. 编写自定义ViewModelFactory

class BooksViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(BooksFragmentViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return BooksFragmentViewModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

2. 调整ViewModel构造函数

确保使用Application Context:

class BooksFragmentViewModel(application: Application) : ViewModel() {
    private val appContext = application.applicationContext
    var books: MutableLiveData<MutableList<BookItem>> = MutableLiveData()
    // 其他成员变量保留...

    init {
        books = bookRepo.booksGetRequest(appContext)
    }
}

3. 在Fragment中用工厂实例化ViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // 通过自定义工厂创建ViewModel
    booksModel = ViewModelProvider(
        this, 
        BooksViewModelFactory(requireActivity().application)
    ).get(BooksFragmentViewModel::class.java)
    // 其他业务逻辑...
}

方案二:使用AndroidViewModel(官方推荐)

AndroidViewModel是ViewModel的子类,它自带Application引用,无需手动传入Context,这是官方推荐的方式,能彻底规避内存泄漏问题:

1. 修改ViewModel继承AndroidViewModel

class BooksFragmentViewModel(application: Application) : AndroidViewModel(application) {
    private val appContext = application.applicationContext
    var books: MutableLiveData<MutableList<BookItem>> = MutableLiveData()
    // 其他成员变量保留...

    init {
        books = bookRepo.booksGetRequest(appContext)
    }
}

2. 在Fragment中实例化ViewModel

AndroidViewModel可以直接通过默认工厂创建,不需要自定义工厂:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    booksModel = ViewModelProvider(this).get(BooksFragmentViewModel::class.java)
    // 其他业务逻辑...
}

额外提醒

  • 你Fragment里原来的setContext方法可以删掉了,我们已经通过安全的方式获取到了Application Context。
  • Volley的RequestQueue建议用Application Context创建,并且最好做成全局单例,避免重复创建造成资源浪费。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:32:34