
Basic Coroutine Level 1
Almost every Android mobile phone works on a multiCore processor. Multithreading or concurrency is an awesome way to use a multi-core processor environment and build fast and efficient applications. Concurrency has a direct relation with Android application Performance.
Kotlin provides a cool and simple way to handle concurrency, Coroutines. In this blog series, I will try to discuss coroutines basic to advance the concept of coroutines. Get your coffee and get ready.
If you have basic knowledge of Coroutines and you want to learn about dispatchers, error handling and etc. Go through the next blog of this series
What are coroutines?
A coroutine is (Very Very)Light Weight Thread. Coroutines have managed by Thread Pool. In other words, Multiple coroutines can run on a single thread which is managed by the Thread pool. We can understand a Thread pool like a program which supervises the concurrent execution of multiple threads waiting to perform tasks. thread pool allocates the tasks to multiple threads and maintains them. Following example show light-weighted coroutines
Try this, You will see 1 Lakh coroutines run very easily. Just Try to run 10k threads :). Your program may get out of memory and your application may crash by creating 10k threads. Let’s discuss what happened behind the scene in the above program. I have used the repeat() method to create 1Lakh coroutines. Thread pool associate number of threads(for example 10 threads) to execute 1Lakhs coroutines. Each thread handles multiple coroutines, execute them, finish them, and get ready for other coroutines. Thread pool handles all the coroutines and executes them behind the scene. Awesome…
We know coroutines are there to solve our two main problems for Android Developer.
- Long-running tasks: these tasks are non UI work which requires different threads. Bitmap processing, downloading data, CPU intensive task and list goes on
- Main-safety allows you to ensure that any suspend function can be called from the main thread.
We will go deeper regarding coroutines. Let us discuss some basic concepts, first. These concepts are used to create, modify, and stop coroutines. The following are some basic conceptual terms that we use in coroutines.
Fundamentals of Coroutines
Scope create and run coroutines(or Start and Stop), provides lifecycle events (runBlocking is a kind of scope )
Context the Scope provides a context in which the coroutine runs
Suspending functions that can be run in a coroutine
(can be suspended)
Jobs a handle on a coroutine
Deferred a future result of a coroutine
Dispatcher manages which thread(s) the coroutine runs on(Main or background)
Let Discuss Scope and let’s get our hand dirty with Some Code.
As we have already read the definition of Scope. It provides life cycle methods for coroutines. It allows us to start and stop coroutines.
Global Scope: Scope of the Entire Application (Global as the name specifies )
RunBlocking: coroutine will run on same the thread
CoroutinesScope: new Scope
The above example is very self-explanatory. we have created coroutine(runblocking) in the main function. runblocking will block current thread (main)and create three coroutines using launch,global-scope, and coroutine scope. global-scope for the entire application. runblocking provides coroutine on the same thread. Let’s move to the next term Context.
In simple words, Context is a set of data(or variables) associated with coroutines. Scope and Context are very related to each other. Coroutine always executes in some context. Scope generates and handles the coroutine and data associated with coroutine is Context.
Coroutine name, Dispatcher(Thread on which coroutine will execute), and Job(handle on the coroutine lifecycle) are examples of context.
In the above example, we have used Dispatcher multiple times to specifies Thread on which Coroutines should work MAIN or IO. Then we use the job to check the status and cancel the job(or coroutine Scope which containing coroutines) if required.
You have noticed one more thing here, withContext(), It allows us to change the context(Type) of thread (IO to MAIN or vise versa, etc) easily. In other words, We can easily switch between the dispatchers. We will discuss more them. But for now, we know that context is data associated with coroutine.
Next Arsenal we have …. The Suspend Functions.
Suspend Functions are functions that can run in coroutines. We can add suspend keyword or modifier in front of the function name. Suspend Function can only be called from Suspend Function or non-suspending scope like runblocking, launch, asyn, etc. let’s take an example of suspend functions to know them more.
Let us discuss what happens in the above program. In the first coroutine, Developers and QA engineers can not work together. First Developer needs to finish the development part and then QA needs to start testing. So suspend functions getNumberQAEngineer() and getNumberDevelopers() need to work sequentially like normal functions. In the Second Coroutine, the application is published both teams can work independently. So Suspend function can work simultaneously.
The First coroutine result will be
total team member seq 69
time taken to complete seq 2023 //time can vary from system to system
The Second coroutine result will be
total team member async 69
time taken to complete async 1076 //time can vary from system to system
Next one is JOB, A Job is a handle on coroutine. .launch() call returns job. It allows us to manipulate the coroutine lifecycle. it can access life cycle methods like cancel( ), join( ) and variable like isCancel, active. job works on a hierarchy(parent-child) level. this means jobs can have children or parents. Job is a very interesting and useful part of coroutines. An interesting fact on job cancellation nature if there is a failure in a child’s job, it will cancel the parent or the same hierarchy job. there are lots of tips and tricks on the job. let us learn a few and take the example of job
In the above example, we have created parent-job coroutine and then created 2 child-job. we easily cancel all the jobs with only canceling the parent job. we can only learn more about the jobs only with practice.
I think we learn a lot lets summarise it
1. coroutines are very light thread.
2. we can create coroutines and handle them with scope and context
3. suspend functions are functions that can run in coroutines.
4. job is a handle on coroutines.
There are more topics in the coroutine remaining exceptions, deferred, etc. For now, we have just touched the surface of the coroutines. But we have completed the most basic concepts of the coroutine. We can only expertise coroutines only by practice. So, Sky is the limit.