Currently, I am trying to optimize my app performance by improving the usage of different Dispatchers and contexts. One question I stumbled upon is that If I launch a suspend function inside a coroutine with a IO Dispatcher, will every other function be executed in the same dispatcher as well?
fun doSomething() {
viewModelScope.launch(Dispatchers.IO) {
getUserData(viewModelScope)
}
}
fun getUserData(innerScope: CoroutineScope) {
workerList.startUserDataWorker()
observeUserData(innerScope) // suspend function, is this called inside the IO Dipatcher?
}
// Will this be called inside the IO Dispatcher?
private suspend fun observeUserData(innerScope: CoroutineScope) {
observerWorkerStateAndPassData(workerList.userDataWorkInfo, USER_DATA_OUTPUT_OPTION).collect { status ->
when(status) {
is Status.Loading -> {
_userDataState.postValue(Status.loading())
}
is Status.Success -> {
// Will getShippingAddressList() also be called on the IO Dispatcher?
_userDataState.postValue(Status.success(getShippingAddressList()))
}
is Status.Failure -> {
_userDataState.postValue(Status.failed(status.message.toString()))
}
}
}
}
// Getting Address from the local room cache. Is this called on the IO Dispatcher?
private suspend fun getShippingAddressList(): List<UserDeliveryAddress> {
val uncachedList = userAddressDao.getAllAddress(UserAddressCacheOrder.SHIPPING)
return userAddressCacheMapper.mapFromEntityList(uncachedList)
}
Aside from the below exceptions, the dispatcher you're using is irrelevant when calling a suspend function. It is only relevant when calling blocking functions. Suspending doesn't use a dispatcher thread.
Exceptions:
withContext(Dispatchers.Main)
, and thereby pass along the main-only restriction up from the view class to your suspend function caller. IMO, since you can avoid the potential problem in the first place using withContext
, you might as well, at least when the suspend function is public. You can use Dispatchers.Main.immediate
to avoid an unnecessary thread switch.withContext(mySingleThreadDispatcher)
so it will still be irrelevant which dispatcher is calling your suspend function.In your example, it doesn't matter what dispatcher calls observeUserData
because the function will suspend indefinitely while it collects. And when it collects, it only calls the non-blocking, thread-safe function LiveData.postValue()
.