【问题标题】:Hilt - inject classes as interfacesHilt - 将类作为接口注入
【发布时间】:2021-06-17 14:09:10
【问题描述】:

假设我有两个接口和两个实现它们的类。

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
}

但这会使应用程序崩溃:

引起:kotlin.UninitializedPropertyAccessException:lateinit 属性 test1 尚未初始化 在 Test2.getTest1(Test2.kt:8) 在 Test2.doSomethingElse(Test2.kt:11)

为什么会这样?

我希望 ITest1 在提供 Test1 时被正确注入,然后绑定到 ITest1 接口。

是否有解决方法来完成这项工作?

【问题讨论】:

    标签: android dagger-2 dagger dagger-hilt


    【解决方案1】:

    通过使用@Provides 方法,您是在自己构建实例,而不是使用 Dagger。因此,Dagger 将允许您这样做,而无需调用您的 @Inject-annotated 方法或填充您的 @Inject-annotated 字段,这样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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多