Kotlin withContext vs Async-await

Authors
  • Amit Shekhar
    Name
    Amit Shekhar
    Published on
Kotlin withContext vs Async-await

I am Amit Shekhar, I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.

Join my program and get high paying tech job: amitshekhar.me

Before we start, I would like to mention that, I have released a video playlist to help you crack the Android Interview: Check out Android Interview Questions and Answers.

In this blog, we will learn about the withContext and Async-await in Kotlin. We will also see how the withContext and Async-await differ from each other and when to use which one.

I will be using this project for the implementation part. If you have not gone through the project, you should go through it and then come back. The project follows a basic MVVM Architecture for simplicity. You can find the complete code for the implementation mentioned in this blog in the project itself.

Let's get started.

withContext is a suspend function through which we can do a task by providing the Dispatchers on which we want the task to be done.

withContext does not create a new coroutine, it only shifts the context of the existing coroutine and it's a suspend function whereas launch and async create a new coroutine and they are not suspend functions.

Let's see the code for the withContext.

private suspend fun doLongRunningTaskAndDoNotReturnResult() {
    withContext(Dispatchers.Default) {
        // your code for doing a long running task
        // Added delay to simulate
        delay(2000)
    }
}

It can also return a result.

private suspend fun doLongRunningTask(): Int {
    return withContext(Dispatchers.Default) {
        // your code for doing a long running task
        // Added delay to simulate
        delay(2000)
        return@withContext 10
    }
}

As withContext is a suspend function, it can be only called from a suspend function or a coroutine. So, both the above functions are suspend functions.

Let's see an example of using the above function:

GlobalScope.launch(Dispatchers.Main) {
    val result = doLongRunningTask()
    showResult(result) // back on UI thread
}

Now, let's have two long-running tasks with results.

private suspend fun doLongRunningTaskOne(): Int {
    return withContext(Dispatchers.Default) {
        // your code for doing a long running task
        // Added delay to simulate
        delay(2000)
        return@withContext 10
    }
}
private suspend fun doLongRunningTaskTwo(): Int {
    return withContext(Dispatchers.Default) {
        // your code for doing a long running task
        // Added delay to simulate
        delay(2000)
        return@withContext 10
    }
}

Let's see an example of using the above two functions.

GlobalScope.launch(Dispatchers.Main) {
    val resultOne = doLongRunningTaskOne()
    val resultTwo = doLongRunningTaskTwo()
    showResult(resultOne + resultTwo) // back on UI thread
}

Here, after approx 4000 milliseconds, it will show the result as it will complete the first task and then only start the second task.

Now, assume that we have to do both tasks in parallel, so we will have to launch two coroutines. So, we can go with the launch or async to launch the coroutines. Here, as we need the result back from the task, so we will have to go with the async as below:

GlobalScope.launch {

    val deferredOne = async {
        doLongRunningTaskOne()
    }

    val deferredTwo = async {
        doLongRunningTaskTwo()
    }

    val result = deferredOne.await() + deferredTwo.await()

    showResult(result) // back on UI thread

}

Here, we are launching two coroutines using the async, so both tasks will run in parallel. After approx 2000 milliseconds only, it will show the result as it will run both tasks in parallel.

The thumb-rules:

  • Both the launch and async are used to launch a coroutine. This enables us to do tasks in parallel.
  • async can be used to get the result that is not possible with the launch.
  • withContext does not launch a coroutine and it is just a suspend function used for shifting the context of the existing coroutine.

Now, we know how the withContext and async-await differ from each other and when to use which one.

You can find the end-to-end implementation in this project.

Prepare yourself for Android Interview: Android Interview Questions

That's it for now.

Thanks

Amit Shekhar

You can connect with me on:

Read all of my high-quality blogs here.