Kotlin withContext vs Async-await

Amit Shekhar
MindOrks
Published in
3 min readJun 2, 2020

In this blog, we are going to 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.

This article was originally published at Outcome School.

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.

That’s it for now.

Also, Let’s become friends on Twitter, Linkedin, Github, Quora, and Facebook.

Clap, share if you like it and follow me for the updates.

--

--

Amit Shekhar
MindOrks

Co-Founder @ Outcome School | Coder | Teacher | Mentor | Open Source | IIT 2010-14 | Android | Machine Learning | Backend