匕首2不识别Kotlin的提供方法。 Java工作正常
匕首不认可Kotlin提供的一种方法。 这是模块的重要部分:
@Provides @AppScope fun provideClient(cache: Cache, interceptors: List<Interceptor>?): OkHttpClient { val httpBuilder = OkHttpClient.Builder() interceptors?.let { for (interceptor in interceptors) { httpBuilder.addInterceptor(interceptor) } } return httpBuilder .cache(cache) .build() } @Provides @AppScope fun provideInterceptors(): List<Interceptor>? { return listOf(HttpLoggingInterceptor().setLevel(WebServiceConfig.LOGGING_LEVEL)) }
错误消息如下所示:
AppComponent.java:15: error: java.util.List<? extends okhttp3.Interceptor> cannot be provided without an @Provides-annotated method.
如果我使用MutableList,那么它工作。 所以问题是:Dagger2 / Kotlin中的列表有什么问题?
原来这是一个泛型互操作问题。
当你在Kotlin中使用一个接口的List
(如Interceptor
)作为参数时,你会发现它具有Java的角度来看列表的类型参数的通配符,因为List
是协变的:
OkHttpClient provideClient(List<? extends Interceptor> interceptors) { ... }
但是,通配符不会被添加到返回类型中。
List<Interceptor> provideInterceptors() { ... }
您可以通过在Java文件中创建模块的实例并查看自动完成提供的方法来检查。
所以问题是Dagger正在寻找一个List<? extends Interceptor>
List<? extends Interceptor>
而你的另一个方法返回一个List<Interceptor>
。
可能的解决方案:
-
使用
@JvmSuppressWildCards
批注来防止添加通配符(请参阅此处的相关问题)。 这可以在任何范围内使用,从整个模块一直到只有单个类型参数都有问题:interceptors: List<@JvmSuppressWildcards Interceptor>?
-
在你正在返回的
List
中添加明确的差异在provideInterceptors
方法。 有趣的是,当你从Java中看到自动完成时,这并不显示,但它修复了构建。fun provideInterceptors(): List<out Interceptor>? { ... }
-
使用
MutableList
接口,正如你所发现的,没有这个问题。
至于为什么只有当你使用List
而不是MutableList
时才会发生这种情况: List
只有在out
位置的类型参数,因此它是协变的。 这将导致通配符为List
生成,但不为不变的MutableList
(这就是为什么工作正常)。
还要注意,这个通配符的生成只在类型参数是一个非最终类型(一个公开类或一个接口)时才会发生。 所以你不会得到这个问题,例如一个List<StringBuilder>
(这是最后一个),但你会得到一个List<BufferedReader>
(不是)。