【问题标题】:Dagger 2: Exposing object from subcomponent in componentDagger 2:从组件中的子组件暴露对象
【发布时间】:2021-03-17 11:49:38
【问题描述】:

我有一个组件:具有@CarScope 作用域的 CarComponent 和具有@DriverScope 作用域的子组件 DriverSubcomponent。基本上汽车需要司机,司机需要头盔。

这是汽车组件:

@CarScope
@Component
interface CarComponent {
    val driverComponentBuilder: DriverComponent.Builder
    fun getCar(): Car
    @Component.Builder
    interface Builder{
        fun build(): CarComponent
        @BindsInstance
        fun carName(@Named("CNAME")  name: String): Builder
        @BindsInstance
        fun driverName(@Named("DNAME")  driverName: String): Builder
    }
}

还有一个驱动子组件:

@DriverScope
@Subcomponent(modules=[HelmetModule::class])
interface DriverComponent {
    fun getDriver(): Driver
    @Subcomponent.Builder
    interface Builder {
        fun build(): DriverComponent
    }
}

头盔模块:

@Module
interface HelmetModule {

    @Binds
    fun bindHelmet(whiteHelmet: WhiteHelmet): Helmet
}

以及对应的类:

@CarScope
class Car @Inject constructor(@Named("CNAME") private val name: String, private val driver: Driver) {
    override fun toString(): String {
        return "Car: $name, Driver: $driver, hash: ${super.toString()}"
    }
}
class Driver @Inject constructor (@Named("DNAME") private val driverName: String, private val helmet: Helmet){
    override fun toString(): String{
        println("Driver Name: $driverName")
        println("Helmet info: $helmet")
        println (super.toString())
        return super.toString()
    }
}
interface Helmet {
    fun putOn(): Boolean
    fun takeOff(): Boolean
}
class WhiteHelmet @Inject constructor() : Helmet {
    override fun putOn(): Boolean {
        println("White Helmet is on")
        return true
    }

    override fun takeOff(): Boolean {
        println("White Helmet is off")
        return false
    }

    override fun toString(): String {
        return "White Helmet"
    }
}

我注意到除非我将 (modules = [HelmetModule::class]) 添加到 CarComponent,否则这段代码将无法编译。看来我调用getCar()的时候,并没有使用DriverComponent提供的Driver,而是创建了所有需要的对象,

我的目标是使用 DriverComponent 提供的 Driver。

有什么方法可以做到这一点? 当前行为是否与我使用的自定义范围有关?

谢谢。 莱泽克

【问题讨论】:

    标签: kotlin dagger-2 dagger


    【解决方案1】:

    DriverComponent 是 CarComponent 的一个子组件。 CarComponent 是一个顶级的组件。这意味着:

    • 您可以直接使用其 Builder 或工厂方法创建 CarComponent。
    • 您不能直接创建 DriverComponent,但是从 CarComponent instance 中,您可以获得可以返回 DriverComponent 的 Builder。您可以重复这个过程,这样一个 CarComponent 实例可能有许多属于它的 DriverComponent 实例。
    • 您从给定 CarComponent 实例创建的任何 DriverComponent 都可以访问该特定 CarComponent 实例的对象图; Driver 和 Helmet 可以直接访问 SteeringWheel 或 CarComponent 中的任何其他内容。
    • CarComponent 无法访问 DriverComponent 中的绑定,因为 CarComponent 可能有零个、一个或多个它创建的 DriverComponent 实例。

    无论您的范围如何,以上所有内容都是正确的;你可以删除它们,它仍然是真实的。但是,由于您使用的是作用域:

    • DriverComponent 中具有 @DriverScope 的绑定将返回相同的实例,无论您从该 DriverComponent 实例中注入它的任何位置。
    • 在 CarComponent 中具有 @CarScope 的绑定将返回相同的实例,无论您从该 CarComponent 实例中注入它的任何位置,从直接在 CarComponent 内的任何位置从您使用 CarComponent 的 Builder 创建的任何 DriverComponent。

    如果您认为以上内容正确——DriverComponent 只能从 CarComponent 实例中创建,并且在创建 CarComponent 之后——那么您的用例与 Dagger Subcomponents for encapsulation 文档相匹配。您需要做的就是绑定一个DriverComponent 的@CarScope 实例,您可以使用可注入的DriverComponent.Builder 创建它。然后,您可以放心地将HelmetModuledriverName 分别移动到您的 DriverComponent 和它的 Builder 上。

    @Provides @CarScope DriverComponent provideDriverComponent(DriverComponent.Builder builder) {
      return builder.build()
    }
    

    或者在 Kotlin 中:

    @Provides @CarScope
    fun provideDriverComponent(builder: DriverComponent.Builder) = builder.build()
    

    您的 Car 将无法直接访问您的 Driver 或他们的 Helmet,但您可以通过向 DriverComponent 添加方法并从该实例获取它们来访问它们。您甚至可以通过注入您的 DriverComponent 并返回 driverComponent.helmet 来编写一个在 CarComponent 中返回 Helmet 的 Provider。

    如果这看起来不正确——也许你的 DriverComponent 不需要任何 CarComponent 绑定,并且你的 Driver 应该能够在没有 CarComponent 实例的情况下创建——那么你可能需要避免使用 Subcomponent 并拥有你的 Driver或 DriverComponent 传递到您的 CarComponent.Builder。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      • 2018-09-17
      • 2015-06-17
      • 1970-01-01
      • 1970-01-01
      • 2015-07-26
      • 1970-01-01
      相关资源
      最近更新 更多