Being inspired from my first lame post about coroutines, this time I decided to get real focus on the coroutines, rather than the setup of Dagger or the ViewModel before the work.
Coroutines are lightweight threads. What this means is that coroutines do not create a real new thread in your processor. These threads are just simple objects which imitate the way of how threads work. Coroutines are created to make asynchronous programming simple.
Note: This posts use cases are in the Android framework.
Add the dependency to your
build.gradle module app file :
Need to know:
To start a coroutine, you need a
CoroutineContext.For that, you will need a
Job and a
Job is nothing more than a way, so you can keep track of what coroutine is doing. Also the job makes working simple because it handles the coroutines according to the
Fragment lifecycle (or the
ViewModel).You can cancel this job when
Fragment has finished.The
CoroutineScope is a combination between the
Dispatchers.*, which is telling the framework what thread the job is going to be executed. If you do not declare a
CoroutineScope will provide it for you. However, you cannot keep track of that job depending on the lifecycle .
The use case:
I need to get some data from the server via Json, the server will give me some values which I will save to the
SharedPreferences. After that I am going to update the UI with those saved values.
Best practice is to use coroutines inside the ViewModel. But if you don’t what to use it, initialise in the Activity/Fragment class.
CoroutineScope is being used in the IO thread. The IO thread is any thread but the Main thread. I could have started the
CoroutineScope on the Main thread, but this is not my use case. My primary work is on the network than in the UI, thus there is pretty logical to me to start the coroutine on the IO thread. The plus operator there just defines the threading policy between the scope and the job. Together they make the
Dispatchers class has 4 types.
- Default: The Default type is used when no
CoroutineContexthas been specified.
- Main: Refers to the main thread, where the UI lies.
- Unconfirmed: A coroutine dispatcher that is not confined to any specific thread.
- IO: Designed for offloading blocking IO tasks to share pool of threads.
Note: You must finish the job when the
ViewModelhas finished. In my case:
First of all I will need to specify the network call using retrofit:
Nothing new here apart from the
Deferred type. The
Deferred type is nothing but a class telling the software that what it provides is going to be delayed. Logic says: don’t run this on the main thread .
Note: I am not providing the retrofit setup.
Also note: As for the
Deferredapproach on Retrofit, it won’t be too long in this way. Please refer this link if you want to know more.
A method inside a coroutine, except from the methods that run on the main thread, must be marked with the
suspend keyword, or on this case should return a
Deferred type, if they return something that delays.
loadPrayerTimes() is the method where the coroutine starts. If a condition is met, I start making the api call, else I need to tell user something (on the main thread).The
withContext is basically the way to change the
CoroutineContex. Now let’s jump to the
makePrayersApiCall() method. It is marked with a
suspend keyword as mentioned before. Everything that runs inside this method, is running on the IO thread. Why? Because that is the scope where I started in the initialisation. Basically, I update the UI on the beginning (where I load some progress bar) and in the end (where I show the data or I show error). One last thing we have not yet mentioned is the
.await() method, which basically makes my request wait, until it gets the response but not by blocking the UI . The execution continues asynchronously.
More to know:
If you want to use kotlin coroutines only in the ViewModel, Google provides some implementation described here.
Using the kotlin coroutines is fun, simple and short. I personally found hard time using RxJava (which is awesome, but hard) and also Java’s AsyncTask.
Coroutines made me understand the asynchronous programming more than I could imagine, and now they are helping me build a full project using them.