Dagger 2 static provider methods in kotlin

后端 未结 5 1424
梦毁少年i
梦毁少年i 2020-12-05 09:20

With the recent versions of dagger 2 one of the improvements made are the possibility of having static provide methods. Simply so:

@Provides
static A provide         


        
相关标签:
5条回答
  • 2020-12-05 09:42

    For the static only approach, I like the solution of zsmb13.

    However, I came here because I wanted to combine @Provides and @Binds within one module. This is not directly possible but with two nested modules (as Omar Al Halabi pointed out).

    I took a slightly different approach for combining @Provides and @Binds:

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

    The differences are:

    • The outer module is an object providing the static functions. This spares using the unintentional companion object.
    • The inner module holds the abstract bindings. I can use an interface here, which spares the abstract modifier in both the class and the function.
    • The outer module includes the inner module so I don't have to include the inner module elsewhere.
    0 讨论(0)
  • 2020-12-05 09:48

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

    Better support for binding declarations within Kotlin companion objects of @Module annotated classes.

    Update dagger dependencies to 2.26 version as

    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"
    

    so now you can use

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

    Important: Soon, adding @Module on companion objects in @Module classes will raise an error.

    Note: For backwards compatibility, we still allow @Module on the companion object and @JvmStatic on the provides methods. However, @Module on the companion object is now a no-op and all of its attributes (e.g. "includes") will be ignored. In future releases, we will make it an error to use @Module on a companion object.

    0 讨论(0)
  • 2020-12-05 09:49

    Although I think zsmb13's solution is better, I found another solution which works

    @Module
    class AModule {
      @Module
      companion object {
        @JvmStatic
        @Provides
        fun providesA(): A = A()
      }
    
      // add other non-static provides here
    }
    

    However, note that there will be two generated classes: AModule_ProvidesAFactory and AModule_Companion_ProvidesAFactory rather than the one AModule_ProvidesAFactory class for the case with an object instead of a class with a companion object

    0 讨论(0)
  • 2020-12-05 09:54

    A great explanation which seems to be Google-approved is at https://github.com/google/dagger/issues/900

    Specifically, see:

    Static provides can be achieved via @JvmStatic. There are two scenarios I see this come up:

    top-level objects

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

    If you have an existing class module, things get a bit weirder

    @Module abstract class DataModule {   
        @Binds abstract fun provideCache(diskCache: DiskCache): Cache
    
        @Module   
        companion object {
            @JvmStatic @Provides fun provideDiskCache() = DiskCache()   
        } 
    } 
    

    The way this works is as follows:

    the companion object must also be annotated as @Module under the hood, the kotlin compiler will duplicate those static provides methods into the DataModule class. Dagger will see those and treat them like regular static fields. Dagger will also see them in the companion object, but that "module" will get code gen from dagger but be marked as "unused". The IDE will mark this as such, as the provideDiskCache method will be marked as unused. You can tell IntelliJ to ignore this for annotations annotated with @Provides via quickfix

    0 讨论(0)
  • 2020-12-05 10:06

    I can't test it right now, but I think this should work:

    @Module
    object AModule {
        @JvmStatic
        @Provides
        fun providesA(): A = A()
    }
    
    0 讨论(0)
提交回复
热议问题