Education

Kotlin Coroutines: An overview of Kotlin Asynchronous Programming

logo

DhiWise

June 22, 2021
image
Author
logo

DhiWise

{
June 22, 2021
}

Summary: Kotlin comes with support for asynchronous programming. The articles focus on the basic concept of asynchronous programming and how Kotlin coroutine simplifies it without affecting the performance and responsiveness of an application.

Kotlin Supports Asynchronous Programming

Asynchronous programming is the need for time to efficiently perform heavy computations such as generating HTTP requests and loading media files from servers. It is critical to avoid situations that can degrade application performance and render your app unresponsive when developing server-side, desktop, or mobile applications.

In almost all mobile applications, asynchronous calls are used to prevent the freezing of screens. It gives the customers an impression that the processes are taking action visually but in reality, it is not. 

Kotlin supports asynchronous codes using coroutine at the language level and it delegates most of the functionality to the kotlinx.coroutines library. 

The use of coroutine is not only limited to asynchronous programming there are other functionalities such as concurrency and actors.

Let us understand why we need Coroutines to perform heavy computations.

The basic concept of Coroutine

Know how an application works.  

When an application is launched, it creates a default thread called the main thread. It is used to perform very small and lightweight operations such as button clicks, UI interactions, and simple mathematical and logical operations. So what about the heavy operations?

Heavy operations are those that take a long time to execute (require an internet connection), it includes operations such as fetching a file from the database, parsing, running database queries, and uploading or downloading an image from the server, among others. 

If we run these heavy operations on the main thread, it will become blocked. It may cause our application to hang, and if an application remains in the same blocked state for an extended period, it may eventually crash. So, how do we solve this issue?

Background thread can solve the block state problem?

Using a background thread, also known as a worker thread, can solve this problem. You can create multiple worker threads to run in the background each for different operations such as network requests, parsing, media downloading, database queries, and so on. 

However, creating and running threads is costly as it consumes too much memory. Creating multiple threads at the same time can run your device out of memory.

As a result, creating multiple numbers of threads is a poor solution for improving the application's performance and responsiveness. 

Here, coroutine comes to the rescue.  

Instead of having multiple background threads, you can have only one thread running in the background, and on that, you can launch multiple coroutines. Each coroutine can be used to perform a single long-running task that requires heavy computations. 

Also, you can initiate suspendable coroutines on the main thread without blocking its operation. The technique is useful in the case of Android applications that are run on a single-threaded platform.  

As a result, your app can perform heavy tasks without interfering with the main thread and using minimum internal memory.

What is coroutine?

Coroutines are lightweight threads that can be suspended and run on top of the thread. When the coroutine is suspended, the corresponding computation is paused, and removed from the thread to be stored in the memory. Meanwhile, the thread is free to be used for other purposes.

They can run concurrently, communicate with one another, and even wait for one another to complete a task. Although they are lightweight threads, their functionality is entirely different from that of threads.

Using threads to perform a heavy task is very expensive as it consumes too much memory to run, while subroutines are almost free. You can create thousands of subroutines without any memory issues.

A coroutine in Android primarily addresses two issues.

  1. The long-running task for heavy computation blocks the main thread.
  2. Main-safety- which allows any suspended function to be called from the main thread.

Let’s dive into each to see how coroutines solve it.

1. Perform long-running tasks without blocking UI 

Every Android application begins with the main thread which is charged with handling UI tasks i.e it coordinates the user interactions. Adding too many operations to the main thread can cause it to become stalled, causing the UI to freeze.

Kotlin coroutines running on the main or the other thread are suspendable. For example, if it is performing the network request, it is suspended to initiate another coroutine, and when the network request returns the result, the computation of the first coroutine is resumed. 

class MainActivity : AppCompatActivity() {
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)

		// coroutine launched in GlobalScope
		GlobalScope.launch() {
		Log.i("Inside Global Scope ",Thread.currentThread().name.toString())
			// getting the name of thread in
			// which our coroutine has been launched
		}

		Log.i("Main Activity ",Thread.currentThread().name.toString())
	}
}

Retrofit's networking library includes native support for the coroutine suspend function. You can make the network call using retrofit and return the result wrapped in the response body, where you can manually check for errors.

2. Main safety, which allows any suspended function to be called from the main thread.

If you are running the coroutines on the main thread then it can be specified using the Dispatcher. To run a coroutine in Kotlin, you must use Dispatcher, whether it is on the main thread or the background thread.

The dispatcher assists in determining which thread the coroutine should be used based on the type of operation. The dispatcher is passed as an argument to the Global Scope by mentioning which type of dispatcher we can use.

There are four types of dispatchers in Kotlin.coroutines.

  • Dispatcher.main 

Here the main thread on Android interacts with UI and performs light work.  It is typically used for UI operations, calling suspended functions, and updating LiveData.

GlobalScope.launch(Dispatchers.Main) {
	Log.i("Inside Global Scope ",Thread.currentThread().name.toString())
		// getting the name of thread in which
			// our coroutine has been launched
	}
	Log.i("Main Activity ",Thread.currentThread().name.toString())

  • Dispacher.IO

It is designed for offloading blocking IO tasks to a shared pool of threads off the main thread. It is mostly used for IO tasks such as database queries, reading and writing files, and networking-related tasks.

GlobalScope.launch(Dispatchers.IO) {
	Log.i("Inside IO dispatcher ",Thread.currentThread().name.toString())
		// getting the name of thread in which
			// our coroutine has been launched
	}
	Log.i("Main Activity ",Thread.currentThread().name.toString())

The room will automatically provide main safety, If you use the suspend function, RxJava, or LiveData. You also don't have to be concerned about primary security when using libraries like Retrofit.

  • Dispatcher.Default

It is optimized for the CPU-intensive work off the main thread. It is used for complex long-running calculations such as parsing JSON and sorting a list.

GlobalScope.launch(Dispatchers.Default) {
		Log.i("Inside Default dispatcher ",Thread.currentThread().name.toString())
			// getting the name of thread in which
			// our coroutine has been launched
		}
		Log.i("Main Activity ",Thread.currentThread().name.toString())

  • Dispatcher.Unconfined

As the name implies, it is not limited to a single thread. It executes the initial continuation of a coroutine in the current call frame and allows the coroutine to resume in whatever thread that is used by the corresponding suspending function, without mandating any specific threading policy.

Kotlin coroutines use structured concurrency to further optimize asynchronous programming,  but this is beyond the scope of this article.

Read this article to know about the other features of Kotlin.

“Do you intend to create an app in Kotlin? DhiWise is an application development platform for web and mobile applications with an intuitive design and advanced technology support. Go agile to build your app faster with DhiWise.

Sign up now!