https://kotlinlang.org logo
Title
c

Colton Idle

02/23/2023, 7:08 PM
If you had Retrofit setup (non suspending) because you have a bunch of places in your code where you already use this... BUT you want your new code to use coroutines, what would you do? I feel like maybe I'd create a new duplicate ApiService and add the suspend modifier and get rid of the Call<> return wrapper type. But keeping two api services in sync seems silly. Am I missing something here for how to use my retrofit apiService in the traditional way + coroutine way?
k

kevin.cianfarini

02/23/2023, 7:13 PM
How do you consume the
Call
objects returned from Retrofit?
c

Colton Idle

02/23/2023, 7:16 PM
I guess I don't really consume them at all (if im understanding your question correctly). At most I'm basically just doing call?.request()
k

kevin.cianfarini

02/23/2023, 7:19 PM
You don’t
Call.execute
anywhere?
or
Call.enqueue
?
c

Colton Idle

02/23/2023, 7:20 PM
enqueue! Sorry 🤦
k

kevin.cianfarini

02/23/2023, 7:20 PM
All good.
Are you certain you want to make the function on the service suspending? You could have a gradual transition by writing an extension on
Call
called
executeSuspending
suspend fun <T> Call<T>.executeSuspending(): Response<T> = suspendCancellableCoroutine { cont ->
  enqueue(object : Callback {
    override fun onResponse(call: Call<T>, response: Response<T>) = cont.resume(response)
    override fun onFailure(call: Call<T>, t: Throwable) = cont.resumeWithException(t)
  }

  cont.invokeOnCancellation { this@executeSuspending.cancel() }
}
This is super crude as I drafted it in Slack, but that’s what I’d do.
Then, once all of your code a layer above your network services uses coroutines you can drop this and use retrofit suspending natively
c

Colton Idle

02/23/2023, 7:28 PM
Are you certain you want to make the function on the service suspending?
I guess not, I'm just used to the "modern" way of calling apiService in my newer projects, but I went back to this codebase and theres no way i can upgrade all of the old stuff. An extension on Call sounds pretty neat actually. idky i didn't think of that.
k

kevin.cianfarini

02/23/2023, 7:29 PM
Godspeed!
c

Colton Idle

02/23/2023, 7:34 PM
1 last thing with this. i guess i want to use suspend from retrofit because i know it handles all of the dispatchers setup (i.e. calling it is main safe). I guess in this case, I wouldn't get the main safety and I'd still need to switch dispatchers myself?
k

kevin.cianfarini

02/23/2023, 7:37 PM
Call.enqueue
internally dispatches call events to a threadpool managed by OkHttp (I’m 99% sure of this, but not certain)
So nothing to worry about with thread safety
/**
   * Asynchronously send the request and notify {@code callback} of its response or if an error
   * occurred talking to the server, creating the request, or processing the response.
   */
  void enqueue(Callback<T> callback);
c

Colton Idle

02/23/2023, 7:37 PM
ah true. forgot that callsbacks are already thread safe.
k

kevin.cianfarini

02/23/2023, 7:39 PM
e

efemoney

02/27/2023, 10:49 AM
Dunno why it isnt mentioned but Retrofit itself includes that extension. Its called
await()
k

kevin.cianfarini

02/27/2023, 1:51 PM
Oh nice, I had no idea
c

Colton Idle

02/27/2023, 2:18 PM
Wait, what? So I don't need the custom executeSuspending() function by Kevin above? theres some built in await function? im on mobile. but will try that in a bit!