Kotlin Coroutine to get started in Android app developement

Sharing is caring!

As an Android developer, we know that every developer deals with thread in their application. A thread plays an important role in development for making the code execution faster and dispatching events easier etc. we all know that the Android system has categorized in two different thread named as the main thread (UI thread) and the worker thread (background thread).

Android recommended using the UI thread for user interface and worker thread for any long operation task is the good approach. So today in this tutorial we will learn about some of the new concepts about the best and optimized thread for android development, which can be the switch easily from main to a background thread and vice versa.

As we know from the beginning of the Android OS version we used the threading concept in our application development. But the journey from the beginning to till now, we have seen many more changes in treading concept in term of optimized to play with both background thread and UI thread. Let’s see all the journey which we faced in our android application development.

Create a Thread for background operation:

Android application development is started by using Java Programming. In Java, we have created the thread with many ways like using the new keyword of Thread class or by using the Runnable Interface. Let’s see by an example to create the normal thread.

Thread thread = new Thread() {
    @Override
    public void run() {
       // do some stuff here
    }
};
thread.start();

This is a simple way to create a normal thread to execute any background work. When tread.start() called, it’s run method will be executed. But the problem is, what should be doing when we need to update any view during this? As all, we know that view can only be updated by UI thread. In this case, we need a Handler thread. Let’s see an example of a Handler.

handler = new Handler();

final Runnable r = new Runnable() {
    public void run() {
        // update the view
        tv.append("Hello World");
    }
};

handler.postDelayed(r, 1000);

Ok, all good here. But the problem is creating the Java Thread Object is always consuming the resource. In Android, we have a very limited shared memory to execute an application. In this case, we need to focus on some other android threading concept which can be work in both backgrounds as well as the main thread.

Our android application most of the time is interacting with the server via network request and response and Android is not allowing to call any network operation work by using the main thread in the newer API version of OS. So let’s focus on what other solution are available to deal with both types of thread to switch easily based on our requirement?

Android Async Task for Network Operation:

I am not going into the detail about this, I think every Android developer has used this asynchronous task for network operation in their application. This is the best-optimized android designed thread for background processing and updating UI. Let’s see an example of the Async Task below.

public class MyAyncTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected void onPreExecute() {
        // Here you can show progress bar or something on the similar lines.
        // Since you are in a UI thread here.
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        // After completing execution of given task, control will return here.
        // Hence if you want to populate UI elements with fetched data, do it here.
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
        // You can track you progress update here
    }

    @Override
    protected Void doInBackground(Void... params) {
        // Here you are in the worker thread and you are not allowed to access UI thread from here.
        // Here you can perform network operations or any heavy operations you want.
        return null;
    }
}

For updating, the view we are the used the callback and the callback is hell, it caused memory leaks most of the time. Why is this memory leaks by using Async Task?  I think it is a valid question. Generally, the Async Task run by two different thread, as we know above half part is executed by the main thread and another half part is executed by the worker thread.

What happened if the Async Task currently held by the worker thread and the same time Android Resouce has killed your application and after a few moments your worker thread has finished the task and it switches back to the main thread for updating the view. But in this situation you view is not available to take the update, it causes the memory leaks.

So in this situation, if something has to observe the life cycle changed and will avoid taking view update if the view is not available. So here comes a new and very popular threading concept called Reactive Rx Java Observable which is observing the view attached or detached life cycle.

Reactive Rx Java Observable:

Rx Java becomes very popular in the Android community. Rx Java provides so many operators, filter and mapping concept. Actually, Rx Java is very vast to use in an android application for many use cases. Rx Android is very popular for switching the thread from Andriod Main Thread to any scheduler thread. Let’s see an example of Rx Java Observable.

private void registerProcess(User user) {
    mCompositDisposable.add(Network.getRetrofit().getUserToken(user)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Response<TokenResponse>>() {
            @Override
            public void onCompleted() {
                // you might do nothing here
            }

            @Override
            public void onError(Throwable e) {
                mProgressbar.setVisibility(View.GONE);
                showSnackBarMessage("Error!");
            }

            @Override
            public void onNext(Response<TokenResponse> tokenResponse) {
                if (tokenResponse.code() == 200) {
                    mProgressbar.setVisibility(View.GONE);
                    showSnackBarMessage("Registration success!");
                } else {
                    mProgressbar.setVisibility(View.GONE);
                    showSnackBarMessage("Registration failed");
                } 
            }
        });
}

Composite Disposable is the container which contains the number of Observables. You will create the instance of this class in onCreate() of the View life cycle and disposed of this onDestroy(). In this, your subscription will be lost and the view will not ready to take the update. It helps to avoid any leaks in your application.

But again the RxJava is very vast and so many operators which makes a very heavy library and for Android application perspective which is not a good approach to use a heavy library for a network task only. I would not be saying that RxJava to use is a bad approach. If you are comfortable with all operators of RxJava then it will make your application up to the next level. Here you need to take care life cycle change because RxJava is not aware of the view life cycle.

But again, now Google has declared that Kotlin will be the new official language for android application development. Kotlin is functional programming which is getting popularity among the Android Community. Kotlin community is now provided a new library which is called the Coroutine which is very lightweight and much compatible with Kotlin.

Start using the Kotlin Coroutine:

Coroutine becomes very popular among android developer which is very supportive in Kotlin. A coroutine is a very lightweight library and best in term of performance in network call. You can use the Dispatcher for switching the thread.

From the reference of stack overflow, kotlinx.coroutines the library you can start new coroutine using either launch or asyncfunction. Conceptually, async is just like launch. It starts a separate coroutine which is a light-weight thread that works concurrently with all the other coroutines.

The difference is that launch returns a Job and does not carry any resulting value, while asyncreturns a Deferred – a light-weight non-blocking future that represents a promise to provide a result later. You can use .await() on a deferred value to get its eventual result but Deferred is also a Job, so you can cancel it if needed. Let’s see by an example to define as an extension of Kotlin of the above statement.

import kotlinx.coroutines.*

fun launchAsync(block: suspend CoroutineScope.() -> Unit): Job {
    return GlobalScope.launch(Dispatchers.Main){block()}
}

suspend fun <T> async(block: suspend CoroutineScope.() -> T): Deferred<T> {
    return GlobalScope.async(Dispatchers.IO) { block() }
}

suspend fun <T> asyncAwait(block: suspend CoroutineScope.() -> T): T {
    return async(block).await()
}
 fun getMovieList() {

        launchAsync {
            try {
                //The data is loading
                setLoading() // ui thread 

                //Request with a suspended repository funcion
                val moviesResponse = repository.loadMovies()

                //non -ui thread, suspend untill the finished
                movieList.value = moviesResponse.await().results

            } catch (t: Throwable) {
                //An error was throw
                setError(t)
                movieList.value = emptyList()
            } finally {
                //Isn't loading anymore
                setLoading(false) // ui-thread
            }
        }
    }

Great, Coroutine is an awesome feature of async call. Let’s see some more about like cancel the coroutine job which is not required to run if our view is got destroyed.

Cancel Coroutine by using Job

You can also use the Job which holds the deferred message to cancel the coroutine.

interface CoroutineContextProvider {
    val main: CoroutineContext
    val io: CoroutineContext
}
private lateinit var contextProvider: CoroutineContextProvider
val main : CoroutineContext by lazy { contextProvider.main }
val io : CoroutineContext by lazy { contextProvider.io }
private val jobs = mutableListOf<Job>()

suspend fun <T : Any> getData(dataProvider : suspend() -> T) : T{
        val deferredData = async(contextProvider.io) { dataProvider() }
        jobs.add(deferredData)
        return deferredData.await()
    }

 fun onDestroy(){
        jobs.forEach(::cancelJob)
        jobs.clear()
    }
    
private fun cancelJob(job: Job){
        if (job.isActive){
            job.cancel()
        }
    }

Here we can call the asynchronous task to get the data which return the deffered<T> response and add this deferred<T> response to the job and make call await function till the suspend finished. If you need to cancel the job for a View is destroy then please cancel all running actively jobs which will cancel the async coroutine. I hope all the stuff will help you make the networking call easy and improved application performance. You can get more in a detail about the Coroutine from this article Android Coroutine Recipes.

Wrapping 

Now we have a good understanding of the Kotlin Coroutine for best-optimized network operation by using Retrofit. You can get the complete Github source code of Kotlin MVVM architecture design with Koin and Coroutine. In my next tutorial, we will learn a few more technical stuff, till then enjoy your healthy day.

If you are wondering to learn Android then Please learn from Android category and wondering to learn Kotlin then Kotlin Category will help you. If you want to learn all the python article, then learn from the python category.

Please do subscribe your email to get the newsletter on this blog on below and if you like this post then do not forget to share like and comment on the below section.

Happy Coding

0 0 votes
Article Rating
Kotlin Coroutine to get started in Android app developement
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Scroll to top
0
Would love your thoughts, please comment.x
()
x