Kotlin withContext vs Async-await

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

I am Amit Shekhar, a mentor helping developers in getting high-paying tech jobs.

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.

Suppose we have two long-running tasks as 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 as 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:

  • 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.
  • An exception in the async block will cancel the parent scope. We will learn how to handle it in the exception handling section.
  • Any exception in the withContext block will get thrown and let us catch without an extra scope.

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.

Master Kotlin Coroutines from here: Mastering Kotlin Coroutines

That's it for now.

Thanks

Amit Shekhar

You can connect with me on:

Read all of my high-quality blogs here.