kotlin中的Dagger 2静态提供程序方法

时间:2017-07-03 21:44:32

标签: kotlin dagger-2

使用最新版本的dagger 2,其中一项改进是可以使用静态提供方法。简单地说:

@Provides
static A providesA() {
  return A();
}

我想知道如何在kotlin做这件事?我试过了

@Module
class AModule {
  companion object {
    @JvmStatic
    @Provides
    fun providesA(): A = A()
  }
}

但我收到错误消息:

@Provides methods can only be present within a @Module or @ProducerModule

我猜这里有与伴侣对象发生的事情,但我对Kotlin来说还是一个新手,而且我不确定如何做到这一点。它甚至可能吗?

谢谢!

5 个答案:

答案 0 :(得分:44)

虽然我认为 zsmb13 的解决方案更好,但我找到了另一个有效的解决方案

@Module
class AModule {
  @Module
  companion object {
    @JvmStatic
    @Provides
    fun providesA(): A = A()
  }

  // add other non-static provides here
}

但是,请注意,对于具有对象而不是具有伴随对象的类的情况,将存在两个生成的类:AModule_ProvidesAFactoryAModule_Companion_ProvidesAFactory而不是一个AModule_ProvidesAFactory类/ p>

答案 1 :(得分:31)

我现在无法测试,但我认为这应该有效:

@Module
object AModule {
    @JvmStatic
    @Provides
    fun providesA(): A = A()
}

答案 2 :(得分:14)

现在Dagger2 (version 2.26) support companion objects in @Module annotated classes in kotlin withthouh @Module and @JvmStatic annotations

更好地支持Kotlin伴侣内的绑定声明 @Module注释类的对象。

将匕首依赖项更新为2.26版本

def dagger_version = "2.26"
//dagger
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"

//If you're using classes in dagger.android you'll also want to include:
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"

所以现在您可以使用

@Module
class AModule {

  companion object {

    @Provides
    fun providesA(): A = A()
  }

}

重要:很快,在@Module类的companion objects上添加@Module引发错误

注意:为了向后兼容,我们仍然允许@Module在 随播对象和@JvmStatic的providers方法。然而, 现在,随播对象上的@Module变为无操作且其所有内容 属性(例如“ includes”)将被忽略。 In future releases, we will make it an error to use @Module on a companion object.

答案 3 :(得分:8)

https://github.com/google/dagger/issues/900

是Google认可的一个很好的解释。

具体请参见:

  

静态提供可以通过@JvmStatic实现。我看到了两种情况:

     

顶级object

@Module object DataModule {   
  @JvmStatic @Provides fun 
    provideDiskCache() = DiskCache() 
} 
  

如果您已有课程   模块,事情变得有点奇怪

@Module abstract class DataModule {   
    @Binds abstract fun provideCache(diskCache: DiskCache): Cache

    @Module   
    companion object {
        @JvmStatic @Provides fun provideDiskCache() = DiskCache()   
    } 
} 
  

其工作方式如下:

     

同伴对象还必须在幕后注释为@Module,   kotlin编译器会将这些static提供方法复制到   DataModule类。匕首会看到这些并将其视为   常规静态字段。匕首也会在同伴中看到它们   对象,但该“模块”将从匕首获取代码生成,但会被标记   为“未使用”。 IDE会将其标记为providerDiskCache   方法将被标记为未使用。您可以告诉IntelliJ忽略此   通过quickfix用@Provides注释的注释

答案 4 :(得分:2)

对于仅静态方法,我喜欢zsmb13的解决方案。

但是,我之所以来到这里,是因为我想在一个模块中合并@Provides@Binds。 这不是直接可能的,但是有两个嵌套模块(如Omar Al Halabi所指出的那样。)

我采用了一种稍微不同的方法来组合@Provides@Binds

@Module(includes = [MyModule.Bindings::class])
object MyModule {
    @Module
    interface Bindings {
        @Binds
        fun bindA(a: AImpl): A
    }

    @Provides
    @JvmStatic
    fun provideB(): B = BImpl()
}

区别是:

  • 外部模块是提供静态功能的对象。这样可以避免使用无意的companion object
  • 内部模块保存抽象绑定。我可以在此处使用一个接口,该接口在类和函数中都保留了abstract修饰符。
  • 外部模块包括内部模块,因此我不必在其他地方包括内部模块。