2017-09-27 63 views
0

我在Kotlin編寫的Android應用程序中使用Retrofit 2來調用API。
我調用看起來如下:改裝call.enqueue阻止第一個請求

val time = measureTimeMillis { 
    val call = geocodingApi.searchByName("Berlin") 
    call.enqueue(object : Callback<GeocodingResponse> { 
     override fun onResponse(call: Call<GeocodingResponse>?, response: Response<GeocodingResponse>?) { 
      // some code 
     } 

     override fun onFailure(call: Call<GeocodingResponse>?, t: Throwable?) { 
      // some code 
     } 

    }) 
} 
Timber.d("searching by name took $time ms") 

的geocodingApi在我的類的構造函數初始化如下:

val loggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { Timber.d(it) }) 
loggingInterceptor.level = HttpLoggingInterceptor.Level.HEADERS 

val client = OkHttpClient 
     .Builder() 
     .addInterceptor(loggingInterceptor) 
     .addInterceptor(GoogleApiKeyInterceptor()) 
     .build() 

val retrofit = Retrofit.Builder() 
     .baseUrl(BASE_URL) 
     .addConverterFactory(ScalarsConverterFactory.create()) 
     .addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build())) 
     .client(client) 
     .build() 

geocodingApi = retrofit.create(GeocodingApi::class.java) 

初始化需要大約80毫秒,這是可以接受的。問題是,第一次調用阻塞UI線程需要1.5到2秒。所有後續的調用都會直接返回,並在通話結束後的一段時間後調用回調。日誌是這樣的:

searching by name took 1864 ms 
searching by name took 3 ms 
searching by name took 4 ms 
searching by name took 2 ms 

結束語在一個單獨的線程中的所有接聽的話會有可能,併產生預期的結果(無UI-阻止),但根據文檔調用call.enqueue應該在後臺執行的結果本身,除了第一次通話外,它適用於所有人。
我做錯了什麼?我正在使用Retrofit 2.3.0和OkHttp 3.8.1。

在此先感謝!

+0

我有同樣的問題。你解決了嗎? – yaneq6

+0

@ yaneq6不幸的不是。我追蹤到由MoshiConverterFactory引起的問題,並轉而使用Gson。我在moshi github頁面創建了一個問題,也許你可以在那裏發表評論,你有同樣的問題:https://github.com/square/moshi/issues/362 – Phoca

回答

1

該問題通過使用附加庫Kotshi並使用它來代替KotlinJsonAdapterFactory來解決。 Kotshi使用kapt在編譯時分析註釋,避免了在運行時解析註釋的巨大開銷。

內改造Builder中的唯一必要的步驟,是
.addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(ApplicationJsonAdapterFactory.INSTANCE).build()))

,並作爲序列化模型的所有數據類應@JsonSerializable進行註釋,以取代
.addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build()))