Retrofit 2.6.0 brings us support for the suspend
function. Call
and enqueue
are used under the hood:
Behind the scenes this behaves as if defined as fun user(...): Call and then invoked with Call.enqueue. You can also return Response for access to the response metadata.
This means that request is asynchronous and network call is being done on the ThreadPoolExecutor
form OkHttp
. We don't care about switching threads as described in this question.
interface ApiService {
@GET("custom/data/api")
suspend fun getData(): String
}
class CustomViewModel: ViewMode() {
// I omitted the initialization of the repository or usecase for simplicity
fun getData() {
viewModelScope.launch { // Dispatchers.Main
apiService.getData() // network call on ThreadPoolExecutor
// continue on Main thread
}
}
}
At this point we have one thread context switching.
But what if I want to do some additional work after network call, for example mapping. And I want to do it not on the main thread:
fun getData() {
viewModelScope.launch { // Dispatchers.Main
val result = apiService.getData() // network call on ThreadPoolExecutor
// continue on Main thread
val uiData = withContext(Dispatchers.IO) { // Coroutine runs on a shared thread pool
mapResult(result) // suspending long running task
}
// continue on Main thread
}
}
At this point we have two thread context switching: one for a network cal, the other for mapping.
And my question is about optimization. Is it more optimized to not use the suspend
function in the Retrofit interface and use one thread switching with coroutine dispatcher on which the network call and other work will run?
interface ApiService {
@GET("custom/data/api")
fun getData(): Call<String>
}
fun getData() {
viewModelScope.launch { // Dispatchers.Main
// Main thread
val uiData = withContext(Dispatchers.IO) { // Coroutine runs on a shared thread pool
val result = apiService.getData().execute().body() // network call
mapResult(result) // suspending long running task
}
// continue on Main thread
}
}
I know that in a simple application the optimization is not that big and is measured in nanoseconds, but that is not the main question. Also, the question is not about the code, exceptions handling etc. The question is about understanding the internal mechanism of multithreading with Retrofit suspend
support and coroutines.