I am using OkHttp to make a synchronous http request. To avoid blocking the main thread, I wrapped the blocking network call in a suspend function and withContext(Dispatchers.IO)
suspend fun run(): String {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build()
return withContext(Dispatchers.IO) {
val response = client.newCall(request).execute()
return@withContext "Request completed successfully"
}
}
Android Studio gives me a warning that execute() is an "Inappropriate blocking method call". My understanding is that execute() will block during the http request taking up a thread in Dispatchers.IO for the duration of the request, which is not ideal. To avoid this issue, I can use the asynchronous version of the request wrapped in suspendCoroutine
suspend fun runAsync(): String = suspendCoroutine { continuation ->
val client = OkHttpClient()
val request = Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
continuation.resumeWithException(e)
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
continuation.resume("Request completed successfully")
}
}
})
}
This avoids the warning, but I do not understand how it is functionally different than the synchronous version above. I am assuming that the async version of the http call uses a thread to wait on the request. Is this assumption correct? If not, how does the async function wait for the callback to return?