Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2 Modules and generic parameters in Kotlin

The question is if Dager 2 supports proper Generic parameters. I have the following test class:

@Module
class Test {

    @Provides
    fun t(
        l: List<String>,
        l1: List<Number> /* Error points to this dependency */
    ): String {

        return "String" + l + l1
    }

    @Provides
    fun list1(): List<Number>{
        throw Error()
    }

    @Provides
    fun list() : List<String> {
        throw Error()
    }
}

in the AppComponent I have usage

@Component(modules = [Test::class])
interface AppComponent {

    fun str(): String
}

When I try to compile I got the following error:

/AppComponent.java:8: error: [Dagger/MissingBinding] java.util.List<? extends java.lang.Number> cannot be provided without an @Provides-annotated method. public abstract interface AppComponent { ^ java.util.List<? extends java.lang.Number> is injected at com.example.android.dagger.di.Test.t(…, l1) java.lang.String is requested at com.example.android.dagger.di.AppComponent.str()

The question is if Dagger support usage of generic parametered types in modules

UPDATE As per @Jeff_Bowman answer, the convenient way of removing wildcards would be with usage on Kotlin typealias, like this:

typealias NumericList = List<@JvmSupressWildcards Number>

@Module
class Test {

    @Provides
    fun t(
        l: List<String>,
        l1: NumericList 
    ): String {

        return "String" + l + l1
    }

    @Provides
    fun list1(): NumericList{
        throw Error()
    }

    ........

}
like image 781
Roman Nazarevych Avatar asked Nov 02 '25 21:11

Roman Nazarevych


1 Answers

java.util.List<? extends java.lang.Number> cannot be provided without an @Provides-annotated method

Note the wildcard: Kotlin defaults to using wildcards in a way that Java does not. You can adjust those types using the @JvmWildcard and @JvmSuppressWildcards to ensure Dagger sees matching declarations.

You have your choice of whether the parameter has wildcards suppressed or whether your @Provides return value has wildcards added. The answer may depend on whether you expect most of your call sites to be Java versus Kotlin.

@Provides
fun t(
    l: List<String>,
    l1: List<@JvmSuppressWildcards Number>  // Note wildcard suppression
): String {
    return "String" + l + l1
}

See also:

  • Dagger in Kotlin: gotchas and Optimizations (Manuel Vivo, July 2019)
  • google/dagger#900: Kotlin+Dagger best practices/documentation/pain points (comment by tasomaniac, October 2017)
  • Dagger 2 with Kotlin, returning type with generic in ApplicationComponent (SO user Bisca, March 2017)
like image 113
Jeff Bowman Avatar answered Nov 04 '25 12:11

Jeff Bowman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!