我在用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。
提前致谢!
答案 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
。