Dagger 2 无法识别 Kotlin 中的 allow 方法。Java工作正常



Dagger 无法识别 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.

如果我使用可变列表,那么它可以工作。因此,问题是:Dagger2/Kotlin 中的列表有什么问题?

事实证明,这是一个泛型互操作问题。

当您在 Kotlin 中使用接口的List(如Interceptor(作为参数时,从 Java 的角度来看,您会看到它具有列表类型参数的通配符,因为List是协变的:

OkHttpClient provideClient(List<? extends Interceptor> interceptors) { ... }

但是,不会为返回类型添加此通配符。

List<Interceptor> provideInterceptors() { ... }

您可以通过在 Java 文件中创建模块的实例并查看自动完成提供的方法来检查这一点。

所以问题是dagger正在寻找List<? extends Interceptor>而您的其他方法正在返回List<Interceptor>

可能的解决方案:

  1. 使用@JvmSuppressWildCards注释可防止添加通配符(请参阅此处的相关问题(。这几乎可以在任何范围内使用,从整个模块一直到您遇到问题的单个类型参数:

    interceptors: List<@JvmSuppressWildcards Interceptor>?
    
  2. provideInterceptors方法中返回的List上添加显式out差异。有趣的是,当您查看 Java 中的自动完成功能时,这不会显示出来,但它修复了构建。

    fun provideInterceptors(): List<out Interceptor>? { ... }
    
  3. 使用MutableList界面,正如您发现的那样,该界面没有此问题。


至于为什么这只发生在你使用List而不是MutableList时:List只在out位置有其类型参数,因此它是协变的。这会导致为List生成通配符,但不为不变MutableList生成通配符(这就是正常工作的原因(。

另请注意,仅当类型参数为非最终类型(开放类或接口(时,才会生成此通配符。所以你不会得到这个问题,比如说一个List<StringBuilder>(这是最终的(,但你会得到它List<BufferedReader>(不是(。

相关内容

  • 没有找到相关文章