代码之家  ›  专栏  ›  技术社区  ›  eleven

使用匕首提供不带接口的实例

  •  1
  • eleven  · 技术社区  · 6 年前

    有一种方法可以在不调用实际构造函数的情况下提供实例。

    class ModelImpl @Inject constructor(...): Model{}
    
    @Provides
    fun model(inst: ModelImpl): Model = inst
    

    如果没有接口,有没有办法做到这一点? Dagger 已经知道的所有依赖项 ModelImpl ,以便创建实例。

    这显然提供了依赖循环:

    @Provides
    fun model(inst: ModelImpl): ModelImpl = inst
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   David Medenjak    6 年前

    当您使用构造函数注入时,匕首可以为您构造对象,并且您已经在使用匕首创建 ModelImpl 将其用作 Model 在你的例子中!

    class ModelImpl @Inject constructor(...): Model{}
    
    @Provides
    fun model(inst: ModelImpl): Model = inst
    
    // somewhere else...
    // both variants would work!
    @Inject lateinit var modelImpl : ModelImpl
    @Inject lateinit var model : Model
    

    如果没有接口,同样可以工作

    class ModelImpl @Inject constructor(...)
    
    // somewhere else...
    @Inject lateinit var model : ModelImpl
    

    如果注释了构造函数,那么Dagger可以为您创建对象(如果可以解析所有依赖项)。无论您在何处请求对象/依赖项,这都是一样的。

    • 作为a中的参数 @Provides 带注释的方法(例如)
    • 作为现场注入特性( @Inject lateinit var )
    • 作为另一个对象构造函数中的参数
    • 作为组件中的提供方法( fun getFoo() : Foo )

    以下所有方法都有效

    // foo and bar can both be constructor injected
    class Foo @Inject constructor()
    class BarImpl @Inject constructor(val foo : Foo) : Bar
    
    @Module
    interface BarModule() {
      @Binds  // you should prefer Binds over Provides if you don't need initialization
      // barImpl can be constructor injected, so it can be requested/bound to its interface here
      fun bindBar(bar : BarImpl) : Bar
    }
    
    @Component(modules = BarModule::class)
    interface BarComponent {
      fun getBar() : Bar // returns barImpl due to binding
    }
    
    @Inject lateinit var bar : BarImpl // but we could as well use the implementation directly
    @Inject lateinit var bar : Foo // or just foo
    

    我建议您从一个小示例开始,然后编译项目并查看生成的代码。如果有什么问题,你会立即得到错误,而你可以四处玩,并尝试不同的设置!

        2
  •  0
  •   eleven    6 年前

    添加到 David Medenjak 安瑟尔如果没有接口,也不需要将实例分组到模块中,那么可以完全忽略模块:

    class Model @Inject constructor(...){
      //...
    }
    
    @Component
    interface SomeComponent{
      fun model(): Model
    }
    
    val model = someComponent.model()