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

Run suspending calls on Dispatchers.Default #3693

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

jingibus
Copy link

Run suspending calls within an optional CoroutineDispatcher, or Dispatchers.Default if none is provided.

Our first call to any Retrofit method is blocked by the initialization of our OkHttpClient (a prerequisite for the creation of a Call). On suspend APIs in Android, this is a problem: up until the invocation of call.enqueue, the caller will be running synchronously on the UI thread, which means the UI thread is blocked waiting on OkHttpClient initialization. This has been causing ANRs for us, even after attempting to work around by triggering initialization earlier in the app's lifecycle.

This fixes the issue by running all calls on a CoroutineDispatcher, either one provided in Retrofit.Builder or, failing that, Dispatchers.Default.

Since this changes forces all exceptions off of the calling stack frame and onto a CoroutineDispatcher, the hacks to get around limitations in exception throwing from Java Proxy objects can be safely removed.

@jingibus jingibus force-pushed the wphillips/2022-02-10/add-coroutine-context branch from cb34de1 to 4bb9250 Compare February 11, 2022 07:03
Copy link

@Egorand Egorand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JakeWharton any thoughts on this?

@jingibus jingibus force-pushed the wphillips/2022-02-10/add-coroutine-context branch from 4bb9250 to 98ad945 Compare March 30, 2022 22:03
@jingibus
Copy link
Author

Modified to remove the public API to set the CoroutineDispatcher. This keeps Kotlin out of the ABI. Instead, always use Dispatchers.Default.

@jingibus jingibus force-pushed the wphillips/2022-02-10/add-coroutine-context branch from 98ad945 to b0770ff Compare March 30, 2022 22:07
@jingibus jingibus changed the title Run suspending calls within CoroutineDispatcher Run suspending calls on Dispatchers.Default Mar 30, 2022
@jingibus jingibus closed this Apr 6, 2022
@jingibus jingibus reopened this May 16, 2022
@jingibus jingibus force-pushed the wphillips/2022-02-10/add-coroutine-context branch from b0770ff to 632bc53 Compare May 16, 2022 21:22
This addresses a need for off-main-thread invocation of
Call.Factory.newCall to support lazy HttpClient initialization.
@jingibus jingibus force-pushed the wphillips/2022-02-10/add-coroutine-context branch from 632bc53 to 84350cc Compare May 24, 2022 23:52
@@ -30,57 +30,63 @@ import kotlin.coroutines.resumeWithException
inline fun <reified T: Any> Retrofit.create(): T = create(T::class.java)

suspend fun <T : Any> Call<T>.await(): T {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use these would be less git changes, and needs to rebase.

suspend fun <T : Any> Call<T>.await(): T = withContext(Dispatchers.Default) {
suspend fun <T : Any> Call<T?>.await(): T? = withContext(Dispatchers.Default) {
suspend fun <T> Call<T>.awaitResponse(): Response<T> = withContext(Dispatchers.Default) {

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

Successfully merging this pull request may close these issues.

3 participants