Ellen Spertus
03/04/2021, 9:26 PMlaunch
(which presumably puts something on another thread) and suspend
functions, which enable that thread to be used for another coroutine?
I'm working in the context of Android, where it's vital that the main thread not get blocked. Why isn't launching a database access, for example, sufficient to guarantee main thread responsiveness? Is the issue that there are a small number of worker threads so no single database access should monopolize one?Casey Brooks
03/04/2021, 9:57 PMlaunch { }
function does it put its block at the back of the queue, but by default it doesn’t change the dispatcher it’s running on. When you launch { }
from the lifecycleScope
or viewModelScope
, you’re posting a task to the dispatcher of that scope, namely Dispatchers.Main.immediate
, which is a dispatcher constrained to a single thread (the Main Thread in Android)
That said, since needing to launch onto a different dispatcher is so common, there’s an overload available that accepts a CoroutineContext
such as <http://Dispatchers.IO|Dispatchers.IO>
, which will launch into that instead of the current dispatcher:
viewModelScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) { }
which is functionally equivalent to
viewModelScope.launch {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) { }
}
Ellen Spertus
03/04/2021, 9:59 PMlouiscad
03/04/2021, 10:57 PMlaunch
does not mean thread switching, it just means launch something (without waiting for it), unlike a plain suspend function call. What is important is that blocking code is wrapped in the the right dispatcher (<http://Dispatchers.IO|Dispatchers.IO>
for I/O like db, files… and Dispatchers.Default
for allocation, other CPU using tasks…)louiscad
03/04/2021, 10:58 PM<http://Dispatchers.IO|Dispatchers.IO> { … }
It works the same with `withContext(Dispatchers.IO) { … }`FYI.