Coroutines and RxJava – Part 1: Asynchronous Handling

Tram Ho

Introduce

In this series of articles, I will be comparing Kotlin Coroutine and RxJava , because they both solve common problem in Android development: Asynchronous handling.

Use case 1: Initialize a heavy object when launching the application

Launch-Time performance is very important. If you want your application to launch quickly, what matters is how you handle Object initialization.

There is some computation that may take some time (eg initializing heavy objects). You don’t want that done in the UI thread! Otherwise, your app will skip frames and the user will experience lag. What could affect this experience? Initialize SDK, create crypto object, …

For this first use case, we just wanted to do a heavy operation in the background thread.

RxJava

Although RxJava is a Reactive Extensions library for JVM, you can also use it to run asynchronous tasks in the background thread.

In this case, we ignore the ability of RxJava to pass element streams, but just want to handle asynchronous processing during initialization.

With RxJava, a Completable will help us to do this. A Completable represents a deferred computation that does not have any value but only returns an indication of completion or exception.

How to use a Completable to initialize the objects we want:

As you can see, we have created a function that will return a Completable object. Inside the function, we are creating a custom Completable with Completable.create will take an emitter (the object will likely register it).

After performing the heavy initialization, we will notify the emitter that it was successful. If there is an error, we will report it. This is because the emitter is of type CompletableEmitter with onComplete and onError being available methods for reporting results to Subscriber .

Another way you can do it is with Completable.fromCallable()

How we can use the above Function: As we already know, Completables is a type of cold Observables in RxJava. That means that only when we subscribe will the code inside Completable.create be executed. Note that it will be executed every time you subscribe.

We must subscribe with the Completable created in the initializeObjectsAsync function.

How do I tell RxJava that we want the initialization to be executed on the background thread? We use the subscribeOn operator to tell RxJava that the code inside Completable.create is executed on the background thread.

Want to make some UI changes once initialization completes, we’ll use the observeOn operator to let RxJava know we want to hear the result on the Android main thread.

Only when you subscribe with Completable , the code inside Completable.create is executed.

After defining the thread, we want to subscribe to start Completable and receive notification when it completes. We do that with .subscribe(successBlockOfCode, failBlockOfCode) . We pass two blocks of code: the first block defines the success scenario and the second block defines the failure scenario.

If we want this code to be executed when creating Activity on Android, we can call this function in onCreate method.

How can we do the same thing with Coroutines?

Kotlin Coroutines

With Coroutines, this is even simpler! Conceptually, coroutine is similar to a thread in many different ways: we can write sequential code that can run on a particular thread.

I will write another post on thread threading in both RxJava and Coroutines. For now, you need to know that we can define the threading policy of a coroutine inside CoroutineContext with a CoroutineDispatcher . We can create a coroutine with a specific CoroutineContext and a CoroutineBuilder .

CoroutineBuilder is a function that creates a Coroutine, runs a block of code, and allows you to access its results in some form. Examples of CoroutineBuilder are: launch, async, runBlocking …

Assuming we want to call the heavyInitialization() as we did earlier in the onCreate method, we can create a Coroutine with CoroutineBuilder launch and do heavy initialization in the currently running code block.

CommonPool CoroutineDispatcher is similar to the Schedulers.computation() in RxJava. This will run the code in the background thread and we don’t have to worry about anything else.

Let’s imitate the example we built with RxJava: we want to know when it finishes initializing heavy objects and handling errors if they happen.

Since the code inside a coroutine (called suspending lambda ) is executed sequentially, the following line of code heavyInitialization() will be executed on initialization success.

As before, we can wrap the function call inside a try catch block to handle the error. It will work in a similar way.

How can we switch to the UI thread and make UI changes? There is a function that you can call inside a Coroutine named withContext that uses another CoroutineContext to run the block of code inside it. It basically switches to the Android UI thread to execute that code.

The CoroutineContext UI we see in the example is not part of the standard Kotlin Coroutines library. Since it is Android specific, it is available in the following library: org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version .

Use Case 2: Handling the background with the Fibonacci problem

For this second Use Case, in addition to implementing something in the background, we also want to return a value. Now, we want to calculate the Fibonacci of a number as the user enters it and click the button to start calculating.

Now we have the following code to calculate the Fibonacci of a number:

How can we compute this value in the background and return the result?

RxJava

We saw most of these concepts in the first use case. We need a building operator of RxJava that can return an object. We can use Single for it!

The code inside Single.create will be executed when we register and can use it the same way we did before. When we receive user interaction, we simply subscribe to the Single which the fibonacci method returns.

You can also use the fromCallable function that we saw in the Completable example:

We pass a numeric value to that function, which will also be used inside the Single.create code block. For example, we can get that number from an EditText.

Every time the user clicks the button, we compute a new Fibonacci number. If the user changes the value inside numberInputEditText , the result will be different!

Kotlin Coroutines

This example is as easy as the example above. When the user clicks the button, we want to start a Coroutine and calculate the Fibonacci of the number entered. We already know everything needed to do that:

Next part?

In the second part of this series we will learn about Canceling Execution !

How do you destroy an Observable? And a Coroutine?

Ref: https://medium.com/capital-one-tech/coroutines-and-rxjava-an-asynchronicity-comparison-part-1-asynchronous-programming-e726a925342a

Share the news now

Source : Viblo