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
相关产品推荐
相关产品推荐

