我在我的Android项目中使用Dagger-Hilt进行依赖注入,现在我有一个基本抽象片段
基本视图模型.kt
abstract class BaseViewModel constructor(
val api: FakeApi,
) : ViewModel() {
//...
}
这里,我有一个依赖项FakeApi
,我尝试做的是将FakeApi
注入到BaseViewModel
中,以便在BaseViewModel
及其所有子对象中可用。
- 我尝试的第一种方法是使用构造函数注入,将其注入到子对象,然后使用构造函数将其传递给超级对象。
任务视图模型.kt
@HiltViewModel
class TaskViewModel @Inject constructor(
api: FakeApi
) : BaseViewModel(api){
}
这种方法工作正常,但我不需要将依赖项从child
传递到super
类,我需要将FakeApi
自动注入BaseViewModel
,而不必传递它,因为我有三个抽象级别(有另一个类继承自TaskViewModel),所以我必须传递它两次。
- 第二种方法是按如下方式使用场注入
基本视图模型.kt
abstract class BaseViewModel: ViewModel() {
@Inject
lateinit var api: FakeApi
//...
}
任务视图模型.kt
@HiltViewModel
class TaskViewModel @Inject constructor(): BaseViewModel() {
}
这种方法对我不起作用,没有注入FakeApi
,我得到了Exception
kotlin.UninitializedPropertyAccessException: lateinit property api has not been initialized
我的问题是
- 为什么磁场注射对我不起作用?
- 有没有办法对
super
类使用构造函数注入,而不是从child
传递依赖项?
3条答案
按热度按时间8tntrjer1#
多亏了这个Github Issue,我发现问题是在ViewModel构造函数初始化期间不能使用字段注入的属性,但是在构造函数(包括所有直接初始化的属性)初始化之后仍然可以使用它。
Dagger首先完成构造函数注入过程,然后进行字段注入过程。这就是为什么在构造函数注入完成之前不能使用字段注入。
使用错误
✔️正确使用
或者可以使用
by lazy
来声明属性。8wigbo562#
我进行了测试,发现
base class
中的场注入仍然适用于Hilt 2.35。我无法像您一样获得错误,因此您可以尝试更改Hilt版本或检查您提供FakeApi
的方式法凯阿皮
主视图模型
应用程序模块
https://github.com/PhanVanLinh/AndroidHiltInjectInBaseClass
ego6inou3#
在互联网上搜索了很多次之后,我认为最好的解决方案是不在ViewModel上使用初始化块
init { ... }
,而是创建一个将在Fragment
上调用的函数fun initialize() { ... }
。基本视图模型.kt
板载视图模型.kt
载入片段.kt
资料来源: