Press Release Software

Kotlin coroutines vs. Java threads vs. Android asynctasks

This year Kotlin was announced as officially supported language by Google. Of course, there’s a lot of information about that language and its benefits, some of us even tried it in their new projects. In this article, I’d like not to focus on the language itself, but rather share some info and my personal impression about an interesting functionality available since Kotlin v.1.1, called coroutines. In general, this is a lightweight alternative to Java Threads and AsyncTasks in Android.

- Advertisement -
- Upgrade your free trial to WhaTech Pro to remove advertising -
In this article, I’d like not to focus on the language itself, but rather share some info and my personal impression about an interesting functionality available since Kotlin v.1.1, called coroutines. In general, this is a lightweight alternative to Java Threads and AsyncTasks in Android.

As far as I know, this is an experimental functionality that is not yet available out of the box. However, enabling it doesn’t take a lot of effort.

- Advertisement -
- Upgrade your free trial to WhaTech Pro to remove advertising -
Just simply add the following to your build.gradle file: kotlin { experimental { coroutines 'enable' } } dependencies { ... compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.18" ...

} repositories { maven { url "https://kotlin.bintray.com/kotlinx/ (link is external)" } } Voila! Coroutines are now enabled! :) Let’s proceed with the examples. The simplest way of using coroutines is launch(CommonPool), where CommonPool is the reusable thread pool and uses java.util.concurrent.ForkJoinPool "under the hood”.

Here is an example: println("Begin") launch(CommonPool){ Thread.sleep(500) // this is blocking example println("Do some async stuff...") } println("End") The output log will show the following: Begin Do some async stuff… End The example above was used for demonstration purposes only, so using such an approach in real life is not recommended. Let’s use a coroutine in a more efficient way.

Here is another example (non-blocking): println("Begin") launch(CommonPool) { for(i in 1..10) { delay(100) //non-blocking example } println("Do some async stuff...") } println("End") The output log in this case will be the following: Begin End Do some async stuff… As we can see now, delay() is similar to Thread.sleep(), but it doesn’t block the thread, only the coroutine from which it was called. Great news! Now let’s do something more advanced with coroutines.

The following example will demonstrate how async() and await() work “under the hood”. For demonstration purposes, let’s create a function that counts a sum of integers from 1 to the value specified as a parameter, i.e.

sum(1) will return 1, sum(10) will return 55, sum(100) will return 5050, etc.: fun sum(num : Int) : Deferred { return async(CommonPool) { var result:Long = 1 for (i in 2..num) { result += i delay(10) // just to check the execution time } result //return statement } } And now let’s make 2 consecutive calls, process them and print the result: println("Begin") launch(CommonPool) { val sum10 = sum(10) val sum100 = sum(100) println((sum10.await() + sum100.await())) } println("End") The log will show the following: Begin End 5105 The interesting fact is that the result will appear in 1.0 second (i.e. 10 ms * 100), meaning that the println statement won’t be executed until all the results from coroutines are returned (de facto when the longest coroutine returns the result).

OK, if this is clear, let’s move to a more practical part, i.e. doing the async stuff and returning results to UI thread.

For this purpose, we can use kotlinx-coroutines-android module that provides UI context for the coroutines (replacing the CommonPool). Just add the following to your gradle file: dependencies { ...

compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.18" ... } Taking into account the mentioned above, passing the result to UI thread looks like following: println("Begin") launch(UI) { val sum10 = sum(10) val sum100 = sum(100) textView1.text = (sum10.await() + sum100.await()).toString() } println("End") Looks like a replacement for AsyncTasks, isn’t it? In this case the following question could be expected: what happens when the context is destroyed (on screen rotation)? I haven’t noticed any issues in this case (like exceptions or memory leaks), everything works like a charm! Here is a more practical example - fetch image, watermark and combine them: launch(UI) { try { val image = ImageUtil.fetchImageByUrl(url1) val watermark = ImageUtil.fetchImageByUrl(url2) //this is async() function val processedImage = combineImages(image.await(), watermark.await()) imageView.setImageBitmap(processedImage.await()) } catch (e : CustomException) { //process the exception } } Therefore, taking this into account, using AsyncTasks with Kotlin makes no sense, coroutines appear to be a very efficient replacement.

Less code, more stability. Say goodbye to lots of callbacks, rotation issues, etc. Amazing! :) In this article, I demonstrated only the most basic aspects of coroutines.

There are lots of other features, just check the official reference: https://kotlinlang.org/docs/reference/coroutines.html (link is external)

News From

Sigma Software - Graphic Design | testingSigma Software
Category: Software DevelopersCompany profile: Sigma Software provides top-quality software development, graphic design, testing, and support services. Systems we develop deliver benefit to customers in automotive, telecommunications, aviation, advertising, gaming industry, banking, real estate, and healthcare. We have advanced skills and ample resources to create large-scale solutions as well as guide startups from idea to profit.