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

ViewModel中注入对象在init块调用非挂起函数后为空的问题

问题核心原因分析

首先看你代码里最明显的错误:重复定义了repo变量——你既在ViewModel的构造函数里通过Hilt注入了repo: JobsRepository,又在类内部声明了@Inject lateinit var repo : JobsRepository。这会导致Hilt的注入逻辑冲突,直接引发后续的空指针问题。

为什么两种写法表现不同?

  • 正常工作的代码:init块里的协程直接使用的是构造函数传入的repo参数,这个参数在ViewModel初始化时已经被Hilt注入完成,所以可以正常调用API。
  • 出问题的代码:getJobsListFromApi里调用的是类内部的lateinit var repo,而这个变量的注入时机晚于init块的执行——当init块调用getJobsList()时,协程启动后,lateinit var repo可能还没被Hilt完成注入,此时访问就会抛出空指针(或者看起来被置空)。

另外你提到“repo在有值后又变为null”,大概率是重复声明的变量被Hilt的注入逻辑覆盖:构造函数传入的repo是有效实例,但后续Hilt尝试注入lateinit var repo时,可能因注入失败导致变量被置为null。

修复方案

直接去掉类内部的@Inject lateinit var repo,把构造函数的参数改为类的属性:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val repo: JobsRepository
) : ViewModel(){

    lateinit var jobDao: JobDao
    
    val jobsListUpdate: MutableLiveData<Resource<JobsResponse>> = MutableLiveData()
    var jobsListResponse: JobsResponse? = null

    init {
       jobDao = repo.getDao() 
       getJobsList()
    }

    fun getJobsList() {
        viewModelScope.launch {
            getJobsListFromApi()
        }
    }

    private suspend fun getJobsListFromApi() {
        jobsListUpdate.postValue(Resource.Loading())
        val response = repo.getAllJobsByAPI()
        jobsListUpdate.postValue(handleBreakingNewsResponse(response))
    }
}

需要补充的信息

如果修复后仍有问题,需要确认:

  • 你的Hilt版本,是否存在ViewModel注入相关的已知bug
  • JobsRepository的注入作用域(比如是否标注了@Singleton、@ViewModelScoped等)
  • 是否有其他代码逻辑(比如自定义ViewModelProvider)对repo变量进行了修改
  • 空指针异常的具体堆栈信息,确认抛出位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:35:42