Here is what I already know:
Retrofit has the enqueue
function and the execute
function. The enqueue
function executes on a different (background) thread and then returns the response using the callback. The execute
function executes on the calling Thread and returns the response directly. enqueue
can be called on the UI Thread while execute
shouldn't be called on the UI Thread.
But I am now wondering, which of the following two options is better.
Call enqueue
in a normal function:
fun makeRequest() {
getCall().enqueue(
object : Callback<ResponseBody> {
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
if (response.isSuccessful) {
//unsuccessful
}
//successful
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
//failed
}
}
)
}
or call execute
in a suspend function on a background thread:
suspend fun makeRequest() = withContext(Dispatchers.IO) {
val call = getCall()
try {
val response = call.execute()
if (!response.isSuccessful) {
//unsuccessful
}
//successful
} catch (t: Throwable) {
//failed
}
}
Which one of these is preferable?
Coroutines have cleaner syntax, so that's a plus. And if you're familiar with coroutine SupervisorJob, you can more easily cancel groups of requests. Other than that, they are largely the same except for which background thread is getting used for the request. But Retrofit already has built-in coroutine support, so your second version can be cleaner than what you have:
suspend fun makeRequest() { // Can be called from any dispatcher
try {
val response = getCall().awaitResponse()
if (!response.isSuccessful) {
//unsuccessful
}
//successful
} catch (e: IOException) {
//failed
}
}
Don’t catch all types by catching the Throwable type. That will swallow CancellationExceptions which would prevent your coroutines from cooperating with cancellation.