使用Dagger提供无界面的实例

时间:2018-12-13 20:16:23

标签: kotlin dagger-2

有一种无需实际构造函数调用即可提供实例的方法。

const xhr = goog.net.XhrIo.send('/api/upload/test-api', () => {
  const obj = xhr.getResponseJson()
}, 'POST', base64encoded)
goog.events.listen(xhr.xhr_, 'progress', ({ event_ }) => {
   console.log('Uploaded ' + event_.loaded + '/' + event_.total)
})

如果没有接口,是否有办法做同样的事情? class ModelImpl @Inject constructor(...): Model{} @Provides fun model(inst: ModelImpl): Model = inst 已经知道Dagger的所有依赖关系,因此它可以创建一个实例。

这显然给出了依赖周期:

ModelImpl

2 个答案:

答案 0 :(得分:1)

在使用构造函数注入时,Dagger可以为您构造对象,并且您已经在使用Dagger创建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可以为您创建对象(如果可以解决所有依赖关系)。无论您在哪里请求对象/依赖项,该方法都是相同的

  • 作为带有注释的方法@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

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

答案 1 :(得分:0)

David Medenjak答案的附加内容。如果没有接口并且不需要将实例分组到模块中,则可以完全省略模块:

class Model @Inject constructor(...){
  //...
}

@Component
interface SomeComponent{
  fun model(): Model
}

val model = someComponent.model()