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()
}
........
}
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: