Kotlin Coroutines on Android — Farewell RxJava?

JetRuby Agency
JetRuby Agency
Published in
5 min readSep 14, 2018

--

Recently, JetBrains announced a new feature, which is known as coroutines (Coroutines are experimental in Kotlin 1.1+). By the way, jetbrains is the place, where you can find the holy grail, aka, “intellij download.”

Coroutines allows simplifying asynchronous programming by putting the complications into libraries.

The inception of this idea appeared in far 1967 in the Simula programming language. At first, there were only several methods: detach and resume (consequently, they allowed stopping and running the performance).

Nevertheless, the idea was abandoned when threads appeared. On the one hand, running an async task in a separate thread makes sense. However, there are some cases, when this solution won’t be effective. Here’s some:

  1. Both threads and switching between them are pretty expensive;
  2. Creating thousands of threads may significantly load the system;
  3. Your code should use only one thread (JavaScript, for example);
  4. You don’t want to use threads as you have a lot of “mutable state”;
  5. You can change UI only from its thread, so it’s easy to get wrong.

Here’s what the developers say about coroutines: “Basically, coroutines are computations that can be suspended without blocking a thread.”

“Without blocking a thread” — what does this mean? Put simply, this is about a function that can be run, detached, and resumed from the same place. Coroutines are a new, convenient way to run non-blocking async operations. Additionally, coroutines creation is much lightweight operation if we compare it with threads.

Suspending functions

The main category in the coroutines is suspending functions.

Detach functions can accept parameters and returnable values as well as usual functions. Additionally, they can be called from coroutines and other suspending functions and the functions’ literals, which are inserted in them.

We mark the methods using a new keyword “suspend.” A function, which is marked this way, can suspend a coroutine’s execution. At the same time, it doesn’t block a thread.

Let’s take a look at how it works in practice. When you specify a suspend function, a compiler modifies a method the following way:

Before:

suspend fun submitPost( token: Token, item: Item): Post {...}

After:

Object submitPost (Token token, Item item, Continuation<Post> cont){...}

The current checkmark, which is stored in the interface, is being transmitted to the method call. As soon as the method stops its performance, a Callback is called and and all the controlling will go to the state machine.

A state machine is an object, which is created by a compiler. It has marks that specify the stages of a code execution. It transmits itself as Callback — Continuation interface.

Nowadays, coroutines have an experimental status. However, this doesn’t mean you can’t use them in your production code. The experimental status shows that their libraries will be expanded. Basically, what this really means, is that their libraries will be expanded and the current challenges will mainly relate to the developers (they’ll have to put their code with all the coroutines into the packet experimental in order to provide post-release transition).

To start using coroutines, you’ll need to add all the necessary dependencies:

Basically, that’s all. You can also wrap your network request into the coroutines:

SuspendCoroutine will stop the current coroutine in order to run an async operation. The result of the operation will be send using continuation that will resume a coroutine.

Nevertheless, this low-level operation is nothing more than only one request. Using coroutines, you can write asynchronous code in an async manner. Take a look at the following example:

You need to specify one crucial thing:

This means that async operations will be executed consecutively and you’ll intentionally have to specify the necessity of parallelism. A competitive execution should be defined clearly.

We described the logic and now we’re ready to start its execution on the highest level. Incidentally, if you forgot to make coroutines builders, a compiler won’t be too happy with it. As a result, you’ll see the following:

A launch is a coroutine’s builder, which call returns instantly. A coroutine will keep working in the background. As a parameter, a builder will accept context, where a coroutine will be executed. Usually, it’s CommonPool and UI.

You may notice a little catch. Suspend functions can be used only from other suspend functions. So we have a launch function, which can be used anyway and within which can be used suspend functions. How does it work?

Coroutine builders are not keywords. They’re the usual functions that accept lambda, which is marked with the keyword suspend. That’s the tricky part.

You may think, “Ah, ok. That’s cool. But what the heck is your coroutine?” The easiest way to imagine what coroutine is to compare it with a lightweight thread. The only difference is that coroutines are much “cheaper” than threads.

And what if you want to run operations concurrently? For this purpose, you’ll need to use coroutine builder async.

The Bottom Line

Nowadays, coroutines represent an effective tool for Backend developers, who work with high load systems. Another cool feature is the possibility to write asynchronous code in a synchronous way.

However, the main question is: “Whether mobile developers should use it instead of Rx java?”

The main drawback of coroutines is that they’re quite poor. Rx java has much more convenient operators. Nevertheless, both solutions have a pretty high barrier of entry and require an in-depth study in order to implement complicated solutions.

Who knows, maybe in some time, coroutines will have an even more convenient set of functions and become a “must-have” solution for mobile developers. We’ll wait and see.

--

--

JetRuby is a Digital Agency that doesn’t stop moving. We expound on subjects as varied as developing a mobile app and through to disruptive technologies.