moshi: When using MoshiConverterFactory in retrofit, the first call blocks main thread
I am using the MoshiConverterFactory in an Android Application written in Kotlin in combination with Retrofit. The first call to retrofit’s enqueue
does not return directly like expected, but takes between one and two seconds to return blocking the UI thread and skipping up to 100 frames.
The problem only occurs when using Moshi, with Gson as Adapter Factory the first call takes longer too, but only around 150ms.
The code I’m using is:
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")
The geocodingApi is initialised in the constructor of my class as follows:
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)
The logs look like this:
searching by name took 1864 ms
searching by name took 3 ms
searching by name took 4 ms
searching by name took 2 ms
I created a sample application to verify the behaviour without my app code: https://github.com/Phoca/KotlinRetrofitMoshiTest
Thanks for investigating!
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 3
- Comments: 20 (8 by maintainers)
Commits related to this issue
- UI set up a retrofit bug that took me hours debugging first run overhead that causing a lot of gc and blocks (kinda) UI https://github.com/square/moshi/issues/362 — committed to hereisderek/trademeapidemo by hereisderek 6 years ago
- Use Kotshi to fix an issue where using MoshiConverterFactory in retrofit, the first call blocks main thread https://github.com/square/moshi/issues/362 — committed to ApplETS/Notre-Dame-Android by Sonphil 6 years ago
Got it. Thanks. This is actually a Retrofit bug (already filed), as it should be lazily initializing this on first usage and on a background thread (if you used enqueue). That being said, I think we’re comfortable with Moshi taking a longer time to initialize an adapter (a one time cost) provided that the actual serialization cost paid over and over is less.
@ShoMasegi Yes, I was using a field named
private
. I already found out this was the cause of the problem, but thanks for the help.Since my original issue is resolved now (for the Googlers with the same problem only reading the last message: Use Kotshi) I’m going to close this issue now. Thanks for your help!
More importantly, how are you testing?
On Fri, Jan 19, 2018, 9:46 AM Louis CAD notifications@github.com wrote: