Coroutine Basics
Coroutines has been a core part of Kotlin for a while now. And more Android libraries are adopting coroutines to handle their internal asnychronous communication. For various use cases, Using Coroutines is defining a suspendible function and executing from a scope. But what is a Coroutine? I wanted to explore this topic in this post.
Coroutines are a suspendible unit of computation. The term suspendible comes from the operating system concept non-preemprive multitasking or Coorperative multitasking. The key takeaway is that system does not initiate a context switch and processes voluntarily give up control upon certain conditions.
Coroutines provide a framework for asynchronous programming. In asynchronous programming, main goal is to not block the primary execution flow and handle occurrence of external and internal events accordingly. In that regards, Coroutines in Kotlin follows a structured concurrency principle. This ensures that there is no memory leak and no process lost during a concurrent computation.
We can dissect the coroutine execution into 3 parts to understand how the structured concurrency is implemented. These are:
- Scope
- Context
- Coroutine
Scopes
Scopes are suspendible code blocks which coroutines can be executed. They are obtained using a Corotuine Builder. There
is one special CoroutineBuilder called RunBlocking
. It can block the thread it is called until all the computation is
finished. So it is mainly used in the main function block or tests.
CoroutineScope
is another building block to create a scope. The main difference is that it does not block the thread
and releases the underlying resources for other tasks.
Context
Context is the set of elements stored in the scope. These elements includes the Job of the coroutine and its Dispatcher type. Any coroutine computation defined with a scope can be considered as a Job. When we structure different coroutines using a child-parent hierarchy, the parent context acquires the children coroutines as a job handle and children coroutine, if not defined otherwise, acquires the parent context. This ensures the structured concurrency.
This code snippet shows that we can compose suspendible functions by nesting it with coroutine builders and acquiring context enables structured control for cancellation and completion.
Coroutine
Suspend modifier adds an additional constraint and it can’t be called within normal functions. Suspendable functions can call other suspendable functions and they can be used to suspend the execution of a coroutine if needed.
These concepts are just the tip of the iceberg, but they are the necessary fundamentals to use the coroutines. You can find more information at Official Kotlin Guides