Dagger 2:从组件中的子组件中暴露 object
Dagger 2: Exposing object from subcomponent in component
我有一个组件:范围为@CarScope 的 CarComponent 和范围为@DriverScope 的子组件 DriverSubcomponent。基本上汽车需要 driver 并且 driver 需要头盔。
这是汽车组件:
@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
}
}
还有一个 driver 子组件:
@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,而是创建所有必需的 objects,
我的目标是使用 Driver 组件提供的 Driver。
有哪些方法可以实现?
当前行为是否与我使用的自定义范围有关?
谢谢。
莱塞克
DriverComponent 是 CarComponent 的 subcomponent。 CarComponent 是一个 top-level 组件 。这意味着:
- 您可以直接使用其 Builder 或工厂方法创建 CarComponent。
- 您不能直接创建 DriverComponent,但是从 CarComponent instance,您可以获得一个 Builder,它可以 return 您 Driver组件。您可以重复这个过程,这样一个 CarComponent 实例可能有许多属于它的 DriverComponent 实例。
- 您从给定 CarComponent 实例创建的任何 Driver组件都可以访问该特定 CarComponent 实例的 object 图; Driver 和 Helmet 可以直接访问 SteeringWheel 或您的 CarComponent 中的任何其他内容。
- CarComponent 无法访问 DriverComponent 中的绑定,因为 CarComponent 可能有零个、一个或多个它创建的 DriverComponent 实例。
无论您的范围如何,以上所有内容都是正确的;你可以删除它们,它仍然是真实的。但是,由于您使用的是范围:
- 具有@DriverScope 的DriverComponent 中的绑定将return 相同的实例,无论您从该DriverComponent 实例中注入它。
- CarComponent 中具有 @CarScope 的绑定将 return 相同的实例,无论您从 CarComponent 实例中注入它,从 CarComponent 或 中的任何地方直接注入任何 Driver您使用 CarComponent 的生成器创建的组件。
如果以上听起来对你来说是正确的——DriverComponent 只能在 CarComponent 实例中创建,在 CarComponent 创建之后——那么你的用例与 Dagger Subcomponents for encapsulation 文档匹配.您需要做的就是绑定 DriverComponent 的单个 @CarScope
实例,您可以使用可注入的 DriverComponent.Builder 创建它。然后,您可以放心地将 HelmetModule
和 driverName
分别移动到 DriverComponent 及其 Builder 上。
@Provides @CarScope DriverComponent provideDriverComponent(DriverComponent.Builder builder) {
return builder.build()
}
或者在 Kotlin 中:
@Provides @CarScope
fun provideDriverComponent(builder: DriverComponent.Builder) = builder.build()
您的汽车将无法直接访问您的 Driver 或他们的头盔,但您可以通过向 Driver 组件添加方法并从该实例中获取它们来访问它们。您甚至可以通过注入您的 DriverComponent 并 returning driverComponent.helmet
.
来编写一个 return 是 CarComponent 中的头盔的 Provider
如果这看起来不对——也许你的 DriverComponent 不需要任何 CarComponent 绑定,并且你的 Driver 应该能够在没有 CarComponent 实例的情况下创建——那么您可能需要避免子组件并将您的 Driver 或 Driver 组件传递到您的 CarComponent.Builder.
我有一个组件:范围为@CarScope 的 CarComponent 和范围为@DriverScope 的子组件 DriverSubcomponent。基本上汽车需要 driver 并且 driver 需要头盔。
这是汽车组件:
@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
}
}
还有一个 driver 子组件:
@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,而是创建所有必需的 objects,
我的目标是使用 Driver 组件提供的 Driver。
有哪些方法可以实现? 当前行为是否与我使用的自定义范围有关?
谢谢。 莱塞克
DriverComponent 是 CarComponent 的 subcomponent。 CarComponent 是一个 top-level 组件 。这意味着:
- 您可以直接使用其 Builder 或工厂方法创建 CarComponent。
- 您不能直接创建 DriverComponent,但是从 CarComponent instance,您可以获得一个 Builder,它可以 return 您 Driver组件。您可以重复这个过程,这样一个 CarComponent 实例可能有许多属于它的 DriverComponent 实例。
- 您从给定 CarComponent 实例创建的任何 Driver组件都可以访问该特定 CarComponent 实例的 object 图; Driver 和 Helmet 可以直接访问 SteeringWheel 或您的 CarComponent 中的任何其他内容。
- CarComponent 无法访问 DriverComponent 中的绑定,因为 CarComponent 可能有零个、一个或多个它创建的 DriverComponent 实例。
无论您的范围如何,以上所有内容都是正确的;你可以删除它们,它仍然是真实的。但是,由于您使用的是范围:
- 具有@DriverScope 的DriverComponent 中的绑定将return 相同的实例,无论您从该DriverComponent 实例中注入它。
- CarComponent 中具有 @CarScope 的绑定将 return 相同的实例,无论您从 CarComponent 实例中注入它,从 CarComponent 或 中的任何地方直接注入任何 Driver您使用 CarComponent 的生成器创建的组件。
如果以上听起来对你来说是正确的——DriverComponent 只能在 CarComponent 实例中创建,在 CarComponent 创建之后——那么你的用例与 Dagger Subcomponents for encapsulation 文档匹配.您需要做的就是绑定 DriverComponent 的单个 @CarScope
实例,您可以使用可注入的 DriverComponent.Builder 创建它。然后,您可以放心地将 HelmetModule
和 driverName
分别移动到 DriverComponent 及其 Builder 上。
@Provides @CarScope DriverComponent provideDriverComponent(DriverComponent.Builder builder) {
return builder.build()
}
或者在 Kotlin 中:
@Provides @CarScope
fun provideDriverComponent(builder: DriverComponent.Builder) = builder.build()
您的汽车将无法直接访问您的 Driver 或他们的头盔,但您可以通过向 Driver 组件添加方法并从该实例中获取它们来访问它们。您甚至可以通过注入您的 DriverComponent 并 returning driverComponent.helmet
.
如果这看起来不对——也许你的 DriverComponent 不需要任何 CarComponent 绑定,并且你的 Driver 应该能够在没有 CarComponent 实例的情况下创建——那么您可能需要避免子组件并将您的 Driver 或 Driver 组件传递到您的 CarComponent.Builder.