Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First call is blocking thread although enqueue is used #2502

Closed
Phocacius opened this issue Sep 28, 2017 · 5 comments
Closed

First call is blocking thread although enqueue is used #2502

Phocacius opened this issue Sep 28, 2017 · 5 comments

Comments

@Phocacius
Copy link

I am using Retrofit 2 in an Android Application written in Kotlin for calling an API.
My call looks as follows:

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 initialisation of the API is fast. The problem is, that the first call takes between 1.5 and 2 seconds blocking the UI Thread. All subsequent calls return directly and invoke the callback some time later when the call is finished. 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

Wrapping all calls in a separate thread would be possible and produces the expected result (no UI-blocking), but according to the documentation calling call.enqueue should execute the result in the background by itself, and it works for all but the first call.
Am I doing anything wrong? I am using Retrofit 2.3.0 and OkHttp 3.8.1.

Thanks in advance!

@swankjesse
Copy link
Member

Unclear what it’s doing without more information. There’s almost nothing that happens in call.enqueue() but it’s possible that initializing your interceptors or OkHttp itself takes time.

@Phocacius
Copy link
Author

Hi Jesse, in the meantime I managed to trace the problem down to Moshi which I used as a json parser. I replaced it with Gson and everything works fine. The first call still takes a bit longer, but it's only around 150ms. Should I close the issue here and open another in the Moshi repo? What additional information can I provide?

@swankjesse
Copy link
Member

Slow moshi is unexpected. Please open an issue there and the kind Moshi maintainers would be happy to help.

@ArcherEmiya05
Copy link

ArcherEmiya05 commented Apr 14, 2021

Good day I still get Choreographer: Skipped 59 frames! The application may be doing too much work on its main thread. on the first initialization. I tried using Kotshi as it was said to be more better by @Phocacius but I see no big difference.

@Ryubal
Copy link

Ryubal commented Jan 25, 2022

Just a note for people with the same issue: I can confirm it was due to a slow initialization when using Moshi. Switched to Gson and the issue went away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants