改造call.enqueue阻止了第一个请求

时间:2017-09-27 09:30:43

标签: android retrofit retrofit2

我在用Kotlin编写的Android应用程序中使用Retrofit 2来调用API 我的电话如下:

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)

初始化大约需要80ms,这是可以接受的。问题是,第一次调用阻塞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。

提前致谢!

2 个答案:

答案 0 :(得分:1)

使用其他库Kotshi解决问题,并使用它代替KotlinJsonAdapterFactory。 Kotshi使用kapt在编译时分析注释,避免了在运行时解析注释的巨大开销。

在Retrofit Builder中,唯一必要的步骤是替换
.addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build()))
通过
.addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(ApplicationJsonAdapterFactory.INSTANCE).build()))

用作可序列化模型的所有数据类都应注明@JsonSerializable

答案 1 :(得分:0)

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(/* your url */)
    .callbackExecutor(Executors.newSingleThreadExecutor())
    // other builder options...
    .build();

使用翻新时使用callbackExecutor