2017-08-02 44 views
0

Dagger無法識別Kotlin中提供的一種方法。這是模塊的重要組成部分:Dagger 2無法識別Kotlin中的提供方法。 Java可以正常工作

@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中的列表有什麼問題?

+0

你可以把你的攔截器提供者放在你的客戶端提供者上,並嘗試重新構建嗎? – savepopulation

+0

這並沒有什麼不同。但我試過了。同樣的問題。 – grenzfrequence

+0

我知道它不應該有所作爲,但我解決了這樣的問題。當你試圖用kotlin使用匕首時,你會遇到一些有趣的問題和解決方案。 – savepopulation

回答

1

原來,這是一個泛型互操作問題。

當你使用一個接口的List(如Interceptor)在科特林參數,你認爲這是有從Java的角度來看列表的類型參數通配符,因爲List是協變:

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

但是,此通配符不會爲返回類型添加。

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

您可以通過創建一個Java文件的模塊的一個實例,看着被自動完成所提供的方法進行檢查。

所以問題是匕首正在尋找一個List<? extends Interceptor>而你的另一種方法是返回List<Interceptor>

可能的解決方案:

  1. 使用@JvmSuppressWildCards註釋,以防止通配符被添加(見一個相關的問題here)。這可以在幾乎任何範圍內使用,從整個模塊一路只在您遇到的問題的單一類型的參數:

    interceptors: List<@JvmSuppressWildcards Interceptor>? 
    
  2. 添加明確out方差的List你」重新在provideInterceptors方法返回。有趣的是,當你從Java中看到自動完成時,這並不顯示,但它修復了構建。

    fun provideInterceptors(): List<out Interceptor>? { ... } 
    
  3. 使用MutableList接口,因爲你已經發現,沒有這個問題。


至於當您使用List而不是MutableList爲什麼這只是發生:List只有在out位置的類型參數,因此,它的協變。這會導致爲List生成通配符,但不會生成不變量MutableList(這就是爲什麼它可以正常工作)。

另請注意,此通配符生成僅在類型參數爲非最終類型(開放類或接口)時纔會發生。所以你不會得到這個問題,說一個List<StringBuilder>(這是最後),但你會得到它的 List<BufferedReader>(不是)。

+0

嘿,非常感謝。我用了3號:MutableList的作品。 – grenzfrequence