Nerd For Tech
Published in

Nerd For Tech

Coroutine & Retrofit

Working with Coroutine and Retrofit and other background tasks

Photo by ThisIsEngineering from Pexels

One can think of a coroutine as a lightweight thread. Like threads, coroutines can run in parallel, wait for each other and communicate. The biggest difference is that coroutines are very cheap, almost free: we can create thousands of them, and pay very little in terms of performance. Threads, on the other hand, are expensive to start and keep around.

Coroutines can be considered as a replacement to AsyncTask for tasks that you want to perform in the background and want your app to be responsive at the same time. No more managing thread on your own. Coroutine provides a very easy way to take the burden off your main thread and return the result to the Main thread once the task is completed.

Why do we need Coroutine?

It helps you manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive
NOTE - Coroutines is recommended solution for asynchronous programming on Android

Features of Coroutine

Lightweight: You can run many coroutines on a single thread due to support for suspension, which doesn’t block the thread where the coroutine is running. Suspending saves memory over blocking while supporting many concurrent operations.
Fewer memory leaks: Use structured concurrency to run operations within a scope.
Built-in cancellation support: Cancellation is propagated automatically through the running coroutine hierarchy.

Breaking down coroutine builders:

  • launch — This builder simply launches a new coroutine and returns a reference to it as a Job object which does not have a result. If you want to block the current thread, instead of launch you may use runBlocking builder instead.
  • async — This builder launches new coroutine and returns a reference to it as a Deferred type object which may have a result. It is usually used along with await which is a suspending function which can wait for a result without blocking the current thread.

And Dispatchers.Main — this isn’t a coroutine builder however we pass it into our launch builder in order to notify the Android system that we will need to update the UI thread at some point during our coroutine execution.

Types of Dispatchers

There are majorly 4 types of Dispatchers.

  1. Main Dispatcher
  2. IO Dispatcher
  3. Default Dispatcher
  4. Unconfined Dispatcher

Main Dispatcher:

It starts the coroutine in the main thread. It is mostly used when we need to perform the UI operations within the coroutine, as UI can only be changed from the main thread(also called the UI thread).

IO Dispatcher:

It starts the coroutine in the IO thread, it is used to perform all the data operations such as networking, reading, or writing from the database, reading, or writing to the files eg: Fetching data from the database is an IO operation, which is done on the IO thread.

Default Dispatcher:

It starts the coroutine in the Default Thread. We should choose this when we are planning to do Complex and long-running calculations, which can block the main thread and freeze the UI eg: Suppose we need to do the 10,000 calculations and we are doing all these calculations on the UI thread ie main thread, and if we wait for the result or 10,000 calculations, till that time our main thread would be blocked, and our UI will be frozen, leading to poor user experience. So in this case we need to use the Default Thread. The default dispatcher that is used when coroutines are launched in GlobalScope is represented by Dispatchers. Default uses a shared background pool of threads, so launch(Dispatchers.Default) { … } uses the same dispatcher as GlobalScope.launch { … }.

Unconfined Dispatcher:

As the name suggests unconfined dispatcher is not confined to any specific thread. It executes the initial continuation of a coroutine in the current call-frame and lets the coroutine resume in whatever thread that is used by the corresponding suspending function, without mandating any specific threading policy. Or in simpler language, an unconfined dispatcher starts a coroutine in the caller thread, but only until the first suspension point. After suspension, it resumes the coroutine in the thread that is fully determined by the suspending function that was invoked.
The unconfined dispatcher is appropriate for coroutines that neither consume CPU time nor update any shared data (like UI) confined to a specific thread.

Difference Between Dispatcher.IO & Dispatcher.Default

The difference is that Dispatcher. Default is limited to the number of CPU cores with a minimum of 2 and maxes up to N where N is the number of CPU cores present. Hence at a time, only N tasks can run in parallel.

On the IO dispatcher, there are by default 64 threads, so there could be up to 64 parallel tasks running on that dispatcher.

The idea is that the IO dispatcher spends a lot of time waiting (IO blocked), while the Default dispatcher is intended for CPU-intensive tasks, where there is little or no sleep.

By now you’ve got yourself familiar with various terms related to coroutine. Let’s jump straight into implementation.

The first step is to include all the dependency that your project requires for this project as mentioned below

The second step is to create our interface class and define the method which is responsible for defining our API Url.

Starting from Retrofit 2.6.0 Retrofit now includes built-in support for Kotlin suspend modifier on functions which means instead of Call<T>, we now have a function with the suspend modifier defined in our interface function. According to Retrofit documentation, this function will behind the scenes behave as a normal Call.enqueue operation.

Suspend function in coroutine is a function that could be started, paused, and resume.

We wrap our response in Response object to get metadata about our request response e.g. information like response code.

The third step is to create our ApiInterfaceBuilder class which is responsible for creating our retrofit client

Now we are done with setting up of everything related to API. Our fourth and final step is to call the API from our activity and fetch its response.

Let's dig deeper into what is happening here. We have used Dispatchers.IO since as per documentation provided all network-related operations should be done using this. The launch keyword simply starts a new coroutine and doesn’t return the result to the caller. The method getCustomerList() runs on a background thread and once it is finished we want the result on the Main thread. We bring our execution from one thread to another using withContext() method. Dispatchers. Main specifies that withContext() method will run on Main thread and hence all the UI related operation should be done inside this method

That’s it for now!!
Thanks for reading and don’t forget to share with your fellow developers :)



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nandish swarup

Nandish swarup

Android | Kotlin | Full stack developer | Blogger