Kotlin withContext vs Async-await

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 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.

Suppose we have two long-running tasks like below:

private suspend fun doLongRunningTaskOne(): String {
    delay(5000)
    return "One"
}

private suspend fun doLongRunningTaskTwo(): String {
    delay(5000)
    return "Two"
}

And now, we can run the two tasks in parallel by using the async-await like below:

fun startLongRunningTaskInParallel() {
    viewModelScope.launch {
        val resultOneDeferred = async { doLongRunningTaskOne() }
        val resultTwoDeferred = async { doLongRunningTaskTwo() }
        val combinedResult = resultOneDeferred.await() + resultTwoDeferred.await()
    }
}

Here if you notice, we have used the async{} which returns an instance of Deferred<T>, which has an await() function that returns the result of the coroutine like we have future in Java in which we do future.get() to the get the result.

Now, let's see what happens if we use withContext instead of the async-await.

fun startLongRunningTaskInParallel() {
    viewModelScope.launch {
        val resultOne = withContext(Dispatchers.IO) { doLongRunningTaskOne() }
        val resultTwo = withContext(Dispatchers.IO) { doLongRunningTaskTwo() }
        val combinedResult = resultOne + resultTwo
    }
}

When we use withContext, it will run the tasks in series instead of parallel.

This is the major difference between the withContext and async-await.

So, when we have a single task to run in the background thread. We should use the withContext. For example like below:

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

Then start it.

fun startLongRunningTask() {
    viewModelScope.launch {
        doLongRunningTask()
    }
}

This way, we can use the withContext.

The thumb-rules:

  • Use withContext when you do not need the parallel execution.
  • Use async only when you need the parallel execution.
  • Both withContext and async can be used to get the result which is not possible with the launch.
  • Use withContext to return the result of a single task.
  • Use async for results from multiple tasks that run in parallel.

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.

Learn System Design for your next Interview from here.

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