Dagger 2 constructor injection in kotlin with Named arguments

20,337

You want to annotate the constructor parameters if you're doing constructor injection, and not the fields - use the @param: annotation target:

@Singleton
class SpiceMix @Inject constructor(@param:Named("oregano") private val oregano: Spice,
                                   @param:Named("sage") private val sage: Spice,
                                   @param:Named("rosemary") private val rosemary: Spice)

Edit: actually, since the resolution order for annotation targets is

  • param;
  • property;
  • field.

according to the docs, having no annotation target should also annotate the parameter of the constructor. So you can just drop the target altogether:

@Singleton
class SpiceMix @Inject constructor(@Named("oregano") private val oregano: Spice,
                                   @Named("sage") private val sage: Spice,
                                   @Named("rosemary") private val rosemary: Spice)
Share:
20,337
Vas
Author by

Vas

The bigger the problem, the more fun it is to solve.

Updated on July 13, 2022

Comments

  • Vas
    Vas almost 2 years

    I have this dependency:

    @Singleton
    class SpiceMix @Inject constructor(@field:[Named("oregano")] private val oregano: Spice,
                                       @field:[Named("sage")] private val sage: Spice,
                                       @field:[Named("rosemary")] private val rosemary: Spice) 
    

    And a module to fulfill its dependencies:

    @Module
    class SpiceModule {
    
        @Provides
        @Named("oregano")
        @Singleton
        fun provideOregano(): Spice = Oregano()
    
        @Provides
        @Named("sage")
        @Singleton
        fun provideSage(): Spice = Sage()
    
        @Provides
        @Named("rosemary")
        @Singleton
        fun provideRosemary(): Spice = Rosemary()
    

    The SpiceMix is then injected in various locations of my app.

    However, this does not compile and I get an error:

    Spice cannot be provided without an @Provides-annotated method
    

    I think the @Named annotations do not quite work in my constructor signature. I am not quite sure how I can make it work.

    Note: this compiles fine if I ditch the Named annotations and change the types of the constructor parameters to their concrete forms. However, Spice is an interface, and I need it for mocking purposes in my tests.

    What can I do?