Kratos
Kratos

Reputation: 957

Coroutines explanation

read a lot about this but still there are some unclear things. The sentence: "coroutines enable writing asynchronous code in synchronous way" is a little bit confusing.

Coroutines are ALWAYS asynchronus. they are basically running on the threads all the time? It is on us to decide which threads will coroutines we declare use (Mainscope- they run on MainThread, CoroutinesScope - it will run on some different threads that are not associated with UI thread??, ViewmodelScope - they will run on the threads that are associated with viewmodel??)

Did I get this right?

Upvotes: 1

Views: 841

Answers (1)

Animesh Sahu
Animesh Sahu

Reputation: 8106

The traditional way most java world write asynchronous is by using "callbacks", which they think and was the only way to write asynchronous tasks by adding listeners for success and failures.

But coroutines way is slightly different. Actually you call a suspend function like delay(ms: Long) and it doesn't seem asynchronous because there isn't any callbacks involved here, but behind the hood the Continuation object would work in place of callbacks to resume it later when needed.

Coroutines are ALWAYS asynchronus

Yes, they are!

They are basically running on the threads all the time?

Yes, they are!

It is on us to decide which threads will coroutines we declare use

Yep, absolutely. They implement Structured Concurrency.

Mainscope - they run on MainThread

Apparantly, yes.

public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)

It creates a CoroutineScope with Context's dispatcher element as Dispatchers.Main to make the children dispatch into the main thread by default (when not specified), and attaches a SupervisorJob to make other children do not being affected by cancellation of one.

CoroutinesScope - it will run on some different threads that are not associated with UI thread??

No, it is upto you to provide the CoroutineDispatcher element to the CoroutineContext that will decide which thread it need to dispatch child coroutines to, for example there are 4 default CoroutineDispatcher:

  • Dispatchers.Main - Dispatches to main thread (single-threaded)
  • Dispatchers.Default - Dispatches to CommonPool (max thread-count same as cores in your processor)
  • Dispatchers.IO - Dispatches to CommonPool (max thread-count: 64)
  • Dispatchers.Unconfined - Dispatches to any thread registered (usually for very small tasks, and is not recommended to be used anyway)

Moreover you can make your own CoroutineDispatcher using java.util.Executors:

Executors.newFixedThreadPool(4).asCoroutineDispatcher() // Your own dispatcher max of 4-threads

There are many other elements in CoroutineContext other than Dispatcher. Like: Job, CoroutineName, CoroutineInterceptor, CoroutineExceptionHandler, etc. I'd recommend reading out this article for better visualization of what's happening with some of the most important Elements of CoroutineContext.

A CoroutineScope is just a wrapper for the CoroutineContext which essentially helps in launching a coroutine using launch or async, you can create one by passing a CoroutineContext as a parameter like: CoroutineScope(Dispatchers.Default + Job() + CoroutineName("My Coroutine")).

Note: All the elements of the CoroutineContext is itself a CoroutineContext, the + sign is overload of plus function defined in CoroutineContext essentially overriding elements from left CoroutineContext with elements from right CoroutineContext (if element does not exist in left it'll just add it).

ViewmodelScope - they will run on the threads that are associated with viewmodel??

ViewModelScope implements Dispatchers.Main by default to launch tasks and they can change UI elements as only main thread can change the UI elements.

SideNote: You can change element of CoroutineContext before launching (overriding one of scope).

Example:

viewModelScope.launch(Dispatchers.Default) {
    // This coroutine is launched under Dispatchers.Default (backed by a CommonPool of threads) instead of Dispatchers.Main
    // but will follow cancellation as soon as lifecycle of Activity associated is destroyed as Job element is not overriden
}

Upvotes: 2

Related Questions