Ham*_*ruf 9 android dependency-injection dagger-hilt
我在我的 Android 项目中使用 Dagger-Hilt 进行依赖注入,现在我遇到了这种情况,我有一个基本的抽象 Fragment
abstract class BaseViewModel constructor(
val api: FakeApi,
) : ViewModel() {
//...
}
Run Code Online (Sandbox Code Playgroud)
在这里,我有一个依赖项是FakeApi. 我想要做的就是注入FakeApi到BaseViewModel要在现有的BaseViewModel和所有的孩子。
@HiltViewModel
class TaskViewModel @Inject constructor(
api: FakeApi
) : BaseViewModel(api){
}
Run Code Online (Sandbox Code Playgroud)
这种方法工作正常,但我不需要将依赖从类传递child给super类,我需要FakeApi将 自动注入到 中BaseViewModel而不必传递它,因为我有三个抽象级别(还有另一个类继承自TaskViewModel) 所以我必须通过它两次。
abstract class BaseViewModel: ViewModel() {
@Inject
lateinit var api: FakeApi
//...
}
Run Code Online (Sandbox Code Playgroud)
@HiltViewModel
class TaskViewModel @Inject constructor(): BaseViewModel() {
}
Run Code Online (Sandbox Code Playgroud)
这种方法对我不起作用,FakeApi没有注入,我有一个Exception
kotlin.UninitializedPropertyAccessException: lateinit property api has not been initialized
Run Code Online (Sandbox Code Playgroud)
super而不是从child?感谢这个Github Issue,我发现问题是你不能在 ViewModel 构造函数初始化期间使用字段注入的属性,但在构造函数(包括所有属性直接初始化)初始化后你仍然使用它。
\nDagger首先完成构造函数注入过程,然后进行字段注入过程。这就是为什么在构造函数注入完成之前不能使用字段注入。
\nabstract class BaseViewModel : ViewModel() {\n\n @Inject\n protected lateinit var fakeApi: FakeApi\n\n val temp = fakeApi.doSomething() // Don\'t use it in direct property declaration\n\n init {\n fakeApi.doSomething() // Don\'t use it in the init block\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nabstract class BaseViewModel : ViewModel() {\n\n @Inject\n protected lateinit var fakeApi: FakeApi\n\n val temp: Any\n get() = fakeApi.doSomething() // Use property getter\n\n fun doSomething(){\n fakeApi.doSomething() // Use it after constructor initialization\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n或者您可以使用 来by lazy声明您的属性。
我进行了测试,发现现场注入base class仍然适用于 Hilt 2.35。我无法像你一样收到错误,所以也许你可以尝试更改 Hilt 版本或检查你如何提供FakeApi
abstract class BaseViewModel : ViewModel() {
@Inject
protected lateinit var fakeApi: FakeApi
}
Run Code Online (Sandbox Code Playgroud)
假API
// Inject constructor also working
class FakeApi {
fun doSomeThing() {
Log.i("TAG", "do something")
}
}
Run Code Online (Sandbox Code Playgroud)
主视图模型
@HiltViewModel
class MainViewModel @Inject constructor() : BaseViewModel() {
// from activity, when I call this function, the logcat print normally
fun doSomeThing() {
fakeApi.doSomeThing()
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序模块
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
fun provideAPI(
): FakeApi {
return FakeApi()
}
}
Run Code Online (Sandbox Code Playgroud)
https://github.com/PhanVanLinh/AndroidHiltInjectInBaseClass
| 归档时间: |
|
| 查看次数: |
371 次 |
| 最近记录: |