https://kotlinlang.org logo
#coroutines
Title
# coroutines
s

Shalom Halbert

12/23/2020, 10:29 AM
When
launch
is used, we use dispatchers
IO
and
Default
to run code asynchronously. Why is
async
run asynchronously if you do not run on one of those dispatchers? It's possible I'm misunderstanding something.
c

Circusmagnus

12/23/2020, 11:53 AM
asynchronously does not mean
in different threads
It just means, that they do not depend on each other, are not synchronized in any way. They may still run in parallel OR be just interleaved on single thread. suspend functions may, well... suspend their execution - waiting for something. This does not block a thread. So, during this suspension, other functions / coroutines may be run on this thread. And, when they finish, our suspend function may resume in the very same thread. Considering code
Copy code
suspend fun one() {
   delay(100)
}

suspend fun two() {
  callSomeOtherSuspendFun
}


singleThreadScope.launch { 
   doSth()
   one()
   doSomeOtherThing()
 }

singleThreadScope.async { two() }
Copy code
We are on single thread. The launch will start first. But soon enough it will suspend for 100 milliseconds. From this moment our async may start executing. It too cuould get suspended, because it is calling suspending function - making room for launch to resume its execution. 

So conceptually, both launch and async are executing at the same time. We cannot know, which one will finish first. They are asynchronous, even, when run on single thread.
That way, if you are on android with Room and Retrofit, you do not have to think about threading at all. Just launch your data-fetching coroutines in
viewmodelScope
(which is run on Dispatchers.Main). They will soon enough suspend, waiting for network calls / db queries to complete. And while they are suspended, other data fetching-corotuines may run on Main Thread. What is more - UI can run on Main thread too, uninterrupted. As long as you are not calling any blocking functions, you are free to go on Main Thread, and just forget about threading completely. *blocking function - function, which will execute for a considerable time, bloking a thread. suspend functions exposed by Room or Retrofit are not blocking, and can be called on Main Thread no problem.
So, IMHO best practice is to: • avoid / wrap blocking functions in
withContext()
• wrap non-blocking callback APIs in
suspendCancellableCorotuine
- which will make coroutine suspend until called back by callback •
launch
and
async
without any Dispatcher specified. If execution needs to be switched to different thread, assume, that
suspend fun
, which you are calling, has taken care of that (via
withContext()
or
suspendCancellableCoroutine
)
s

streetsofboston

12/23/2020, 1:53 PM
Yup, Asynchronous != Parallel You can run asynchronously on a dispatcher with only one thread. The current call may suspend and start executing (resuming) an other suspended call. When that one is done, it may resume the first call again. Like a queue of tasks served by a single thread, being served and run one at a time. With multiple threads in a dispatcher, this not only happens asynchronously, but they may run in parallel as well. Asynchronous is; not finishing one call/function and starting or resuming another one. Doesn't say anything about being parallel or not. Parallel is; calls run at the same time. Often this implies they run asynchronously as well, but not necessarily.
3 Views