Hilt - 将 类 作为接口注入
Hilt - inject classes as interfaces
假设我有两个接口和两个实现它们的 类。
interface ITest1 {
fun doSomething()
}
interface ITest2 {
fun doSomethingElse()
}
class Test1 @Inject constructor(): ITest1 {
override fun doSomething() {
println("Something")
}
}
class Test2 @Inject constructor(): ITest2 {
@Inject
lateinit var test1: ITest1
override fun doSomethingElse() {
test1.doSomething()
println("Something else ")
}
}
如果我使用@Bind,我可以完成这项工作:
@Module
@InstallIn(SingletonComponent::class)
internal abstract class DependenciesBindings {
@Singleton
@Binds
abstract fun bindTest1(test1: Test1): ITest1
@Singleton
@Binds
abstract fun bindTest2(test2: Test2): ITest2
}
但我想在注入它们之前对 类 做一些配置。为此,我尝试使用 @Provide:
@Module(includes = [DependenciesBindings::class])
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(): Test1 {
return Test1()
}
@Singleton
@Provides
fun provideTest2(): Test2 {
return Test2()
}
}
@Module
@InstallIn(SingletonComponent::class)
internal abstract class DependenciesBindings {
@Singleton
@Binds
abstract fun bindTest1(test1: Test1): ITest1
@Singleton
@Binds
abstract fun bindTest2(test2: Test2): ITest2
}
但这会使应用程序崩溃:
Caused by: kotlin.UninitializedPropertyAccessException: lateinit
property test1 has not been initialized
at Test2.getTest1(Test2.kt:8)
at Test2.doSomethingElse(Test2.kt:11)
为什么会这样?
我希望在提供 Test1 时正确注入 ITest1,然后绑定到 ITest1 接口。
是否有解决方法可以使此工作正常进行?
通过使用 @Provides
方法,您可以自己构建实例,而不是使用 Dagger。因此,Dagger 将允许您在不调用 @Inject
注释方法或填充 @Inject
注释字段的情况下这样做,这样 getTest1
将在未初始化的字段上失败。
一个更常见的模式可能让 ITest2 的绑定注入一个 Test2 实例(毕竟,@Provides
methods can take arguments from the graph),这允许 Dagger 创建 Test2 实例并允许您在返回之前对其进行操作:
@Module(/* no includes */)
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(test1: Test1): ITest1 {
// manipulate test1
return test1
}
@Singleton
@Provides
fun provideTest2(test2: Test2): ITest2 {
// manipulate test2
return test2
}
}
如果您不能让 Dagger 直接创建您的 Test1 或 Test2——例如,如果您无法控制构造函数——您可以注入一个 MembersInjector<Test1>
并使用它来注入 @Inject
字段和方法。
@Module(includes = [DependenciesBindings::class])
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(injector: MembersInjector<Test1>): Test1 {
val test1 = Test1()
injector.injectMembers(test1)
return test1
}
@Singleton
@Provides
fun provideTest2(injector: MembersInjector<Test2>): Test2 {
val test2 = Test2()
injector.injectMembers(test2)
return test2
}
}
假设我有两个接口和两个实现它们的 类。
interface ITest1 {
fun doSomething()
}
interface ITest2 {
fun doSomethingElse()
}
class Test1 @Inject constructor(): ITest1 {
override fun doSomething() {
println("Something")
}
}
class Test2 @Inject constructor(): ITest2 {
@Inject
lateinit var test1: ITest1
override fun doSomethingElse() {
test1.doSomething()
println("Something else ")
}
}
如果我使用@Bind,我可以完成这项工作:
@Module
@InstallIn(SingletonComponent::class)
internal abstract class DependenciesBindings {
@Singleton
@Binds
abstract fun bindTest1(test1: Test1): ITest1
@Singleton
@Binds
abstract fun bindTest2(test2: Test2): ITest2
}
但我想在注入它们之前对 类 做一些配置。为此,我尝试使用 @Provide:
@Module(includes = [DependenciesBindings::class])
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(): Test1 {
return Test1()
}
@Singleton
@Provides
fun provideTest2(): Test2 {
return Test2()
}
}
@Module
@InstallIn(SingletonComponent::class)
internal abstract class DependenciesBindings {
@Singleton
@Binds
abstract fun bindTest1(test1: Test1): ITest1
@Singleton
@Binds
abstract fun bindTest2(test2: Test2): ITest2
}
但这会使应用程序崩溃:
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property test1 has not been initialized at Test2.getTest1(Test2.kt:8) at Test2.doSomethingElse(Test2.kt:11)
为什么会这样?
我希望在提供 Test1 时正确注入 ITest1,然后绑定到 ITest1 接口。
是否有解决方法可以使此工作正常进行?
通过使用 @Provides
方法,您可以自己构建实例,而不是使用 Dagger。因此,Dagger 将允许您在不调用 @Inject
注释方法或填充 @Inject
注释字段的情况下这样做,这样 getTest1
将在未初始化的字段上失败。
一个更常见的模式可能让 ITest2 的绑定注入一个 Test2 实例(毕竟,@Provides
methods can take arguments from the graph),这允许 Dagger 创建 Test2 实例并允许您在返回之前对其进行操作:
@Module(/* no includes */)
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(test1: Test1): ITest1 {
// manipulate test1
return test1
}
@Singleton
@Provides
fun provideTest2(test2: Test2): ITest2 {
// manipulate test2
return test2
}
}
如果您不能让 Dagger 直接创建您的 Test1 或 Test2——例如,如果您无法控制构造函数——您可以注入一个 MembersInjector<Test1>
并使用它来注入 @Inject
字段和方法。
@Module(includes = [DependenciesBindings::class])
@InstallIn(SingletonComponent::class)
object Dependencies {
@Singleton
@Provides
fun provideTest1(injector: MembersInjector<Test1>): Test1 {
val test1 = Test1()
injector.injectMembers(test1)
return test1
}
@Singleton
@Provides
fun provideTest2(injector: MembersInjector<Test2>): Test2 {
val test2 = Test2()
injector.injectMembers(test2)
return test2
}
}