Kotlin Coroutine on Android

Kotlin Coroutine on Android
Kotlin Coroutine on Android

A coroutine is referred to as a concurrency design pattern that is reduced for simplification and enhancement of asynchronously executable codes. Coroutines were first included in Kotlin, that too in version 1.3.

The conceptual framework for using coroutines in Android comes from the other short-hand programming languages, such as JavaScript, Python, C# and Ruby. Coroutines were used for the first time in 1967, in the programming language Simula. Kotlin takes the advantage of the cooperative nature of functions for co-ordinating routines that consist of lightweight threads written on the basis of the original threading framework.

In Android, coroutines are primarily employed to manipulate the long-running tasks that may otherwise interfere in the working of the main thread and lead to the crashing of the app. The survey indicates that more than half of professional developers who incorporated coroutines in their source code have observed a hike in productivity as it allows the developers to write well-structured and concise app codes.

Asynchronous programming is extremely crucial for the efficient working of modern apps. It allows us to schedule tasks parallelly, which saves the overall execution time of any given task. This in return allows developers to process the heavy-resources or high computing power tasks away from the UI thread, in the BackgroundWorker classes. With this, you can escape the freezing of user-interfaces and provide a smooth experience to your users.

Android provides a wide chain of asynchronous programming mechanisms; this makes it very difficult for developers to pick the most suited one for their project requirements. Some mechanisms have multi-phased and wide-stretched learning curves, while some require tons of boilerplate codes. In both these cases, the developers’ time is wasted unethically.

This hampers the overall scalability of the project and increases the cognitive load on beginners. Therefore, it is recommended to use APIs that are concise, efficient and scalable. Since all the APIs available on the JVM at that time had this common issue, one of the efficient JetBrains unit came up with a contemporary API-known as “Kotlin Coroutines”. It has a uniform learning curve and comes with a bundle of default methods and tutorials.

On Android, coroutines are widely used for solving two problems:

  • Long-running tasks: This issue arises when any task takes a very long time for execution and interrupts the main task.
  • Main-safety: It allows you to invoke any suspended function from the main thread.

Coroutines and Threads:

A coroutine can also be considered as a light-weight thread. A lightweight thread implies it doesn’t map on the native thread, due to this it doesn’t require context switching on the processor. A lightweight thread means it doesn’t map on the native thread, so it doesn’t require context switching on the processor, therefore, they are faster. Analogous to threads, coroutines run parallelly, wait for the execution of one another if required and communication among themselves. With this, we interfere that both Coroutines and the threads are implemented for multitasking.

Working of a Coroutine
Image Source: www.medium.com

The key difference between a thread and a coroutine is that the earlier is managed by the operating system, while the latter one is managed by the developers, as it was devised to incorporate parallelism on the basis of function co-operation. Coroutines can be implemented freely, that is, you can create thousands of coroutines without compromising the system performance. Conversely, True threads are expensive to initiate and maintain, each thread is created at the stake of the system performance, maintaining a thousand threads can be a grave challenge for a modern machine.

Working of a Thread
Image Source: Mindworks

Coroutines do not replace threads; they are more like a framework to manage them. Coroutines were previously available in many languages. Primarily, there are two types of Coroutines: Stackless and Stackful. Kotlin coroutines are stackless, it means that the coroutines don’t come up with their own stack, so they aren’t allowed to map on the native thread.

Features of Coroutines

  • Reduced memory leaks: It uses structured concurrency strategy for running operations in a given scope.
  • Built-in cancellation support: Cancellation can be automatically propagated via the running coroutine hierarchy.
  • Lightweight: Kotlin allows us to launch multiple coroutines on a single thread due to support for suspension, which doesn’t block the thread, that contains the running coroutine. Suspending cuts down the memory over blocking along with supporting several concurrent operations.
  • Jetpack integration: A large number of Jetpack libraries include extensions that are compatible with full coroutines support. Some of these libraries also provide default coroutine scope that facilitates structured concurrency to a very high extend.

Coroutine Terminology

Kotlin provides an efficient bundle of API so that you may align your asynchronous code sequentially.

blog banner 1

Consider this snippet of code as an example:

  • val snowyBitmap = getFilteredBitmap()
  • showBitmap(bitmap)

To fetch the bitmap from a specific API and apply the snow filter, we use the showBitmap() function and select the snowyBitmap from getFilteredBitmap().

Due to the high execution time, such sequential codes may also intervein between certain vital operations, therefore they should be placed in the distinct thread. This can be achieved by encapsulating such sequential codes in a Kotlin Coroutine.

For implementing Coroutines you need to have a proper understanding of the Coroutine terminology:

  • Suspending functions: The set of functions, which can be suspended without blocking the execution of the current thread. Rather than only returning a specific value, they also maintain the record of the context in which the caller suspends it. With the help of the context, we may resume them if required.
  • CoroutineBuilders: These functions have certain prerequisites; particularly a suspending lambda has to be passed as an argument to initiate a coroutine. Some widely used coroutine builders provided by Kotlin Coroutines are, async(), launch(), runBlocking.
  • CoroutineScope: It is used to indicate and manipulate the lifecycle of Kotlin Coroutines. It can be used throughout the application or can be restricted to a specific. Android Activity or fragment. You need to manipulate the scope to trigger the coroutine.
  • CoroutineDispatcher: It defines the thread pool so that you may launch your Kotlin Coroutines. It can be used to define various kinds of thread pools, namely, background thread pool, main thread pool, or several custom thread pools. You can also use this to toggle between threads or fetch results from them and pass them to other activities.

Prerequisites for Coroutine

With reference to the Kotlin Coroutines Github repository, prior to using coroutines in our source code, you need to import the kotlinx-coroutines-core and kotlinx-coroutines-android. Both of these libraries assist the Android main thread analogous to the library io.reactivex.rxjava2:rxandroid for RxJava and make sure to log the uncaught exceptions before the Android application crashes.

Moreover, if your project is RxJava based to make sure that you include kotlinx-coroutines-rx2 for implementing coroutines with RxJava also. This library assists in transferring RxJava to Coroutines. You need to import the following libraries in your Android project, in the app/build.gradle.

  • implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2’
  • implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2’
  • implementation “org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.3.2”

Step Two: Include the latest Kotlin version in you build.gradle file

buildscript {
ext.kotlin_version = ‘1.3.50’
repositories {
jcenter()

}

}

Implementing Suspended Functions

If you intend to extract your workload into partitioned functions. (Let’s say that it takes a lap of thousand milliseconds and then,

returns the number).
fun workload(n: Int): Int
{
delay(1000)
return n
}

You will encounter a pop-up that displays a very familiar error, which says:

“Suspend functions are only allowed to be called from a coroutine or another suspend function.”

Now let’s try to understand what this indicates. The prime advantage of using coroutines is that they are allowed to suspend without blocking a thread. The compilers need to emit some specific codes for achieving this, so we need to add the keyword suspend explicitly in the code. We use the suspend modifier for it:

suspend fun workload(n: Int): Int {
delay(1000)
return n
}

Now if you call  workload() via a coroutine, the compiler is already aware that it might suspend and will release the resources accordingly:

GlobalScope.async {
workload(n)
}

The workload() function can be invoked within a coroutine (or any alternate suspending function), but it can’t be invoked from an exterior ecosystem, apart from the coroutine. It is obvious that delay() and await() functions that are used above declared themselves as suspend, and that’s why you need to encapsulate them with the runBlocking {}, launch {} or async {}.

Nowadays, coroutines have been deep-rooted in modern programming languages. They are easy to learn and implement and come with a wide set of advantages and utilities. We recommend the use of Kotlin coroutines in Android so that the end app becomes less prone to app crashes and sustainable.

Most of the apps based on AI technologies such as handwriting recognition, speech recognition, face detection use coroutines are these threads are very time-consuming, if they are directly linked to the user-interface they deteriorate the overall user-experience by blocking the main thread in execution.

To learn more about Android Development, click here.

By Vanshika Singolia