Dagger 2没有认识到Kotlin中的提供方法。 Java工作得很好

时间:2017-08-02 10:04:46

标签: android kotlin dagger-2

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.

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

1 个答案:

答案 0 :(得分:3)

原来这是一个泛型互操作问题。

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

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

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

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

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

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

可能的解决方案:

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

    interceptors: List<@JvmSuppressWildcards Interceptor>?
    
  2. 在您out方法中返回的List上添加明确的provideInterceptors差异。有趣的是,当您从Java查看自动完成时,这并没有显示,但它修复了构建。

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

  4. 至于为什么只有当您使用List而不是MutableList时才会发生这种情况:List只有out位置的类型参数,因此,它是协变的。这会导致为List生成通配符,但不会为不变MutableList生成通配符(这就是为什么工作正常)。

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