Question Details

No question body available.

Tags

android kotlin async-await kotlin-coroutines

Answers (2)

Accepted Answer Available
Accepted Answer
June 21, 2025 Score: 5 Rep: 21,336 Quality: Expert Completeness: 80%

Yes, calling await immediately after async is nonsense. It is basically the same as simply writing

val currentWeather = getCurrentData()
val forecastWeather = getForecastData()

You gain nothing, but you incur the overhead of launching two coroutines and having overcomplicated code which leaves the reader to wonder why, effectively decreasing the readability of the code.

If you want the two functions to be executed in parallel you have to call them like you proposed, calling await later:

val currentWeather = async { getCurrentData() }
val forecastWeather = async { getForecastData() }

WeatherHomeUiState.Success(Weather(currentWeather.await(), forecastWeather.await()))

Please keep in mind, though, that the code is only allowed to run in parallel now, if it actually is run in parallel depends on how the two functions actually work. Since the viewModelScope uses the Main dispatcher which only has a single thread (the Main thread), the new coroutines that are launched in that scope will also run on that single thread. True parallelism can only be achieved by using multiple threads, though.

There are two options to mitigate that:

  1. Only if at least one of the two functions switches to another dispatcher (with withContext(Dispatchers.IO) { ... }, for example) their coroutine is moved to another thread where it runs in parallel to the rest.

  2. Even if the two functions stay on the same thread their execution may overlap. Although only at most one coroutine can run on the thread at any given time, if the first coroutine is suspended (which could happen when getCurrentData() waits for some network data to arrive, for example), then the second coroutine can occuppy the thread. Only when that suspends itself (or eventually finishes) the first coroutine continues (still on the same thread). When the majority of the execution time of the two functions consists of waiting, this waiting can be done in parallel. That works because you don't need a thread to wait. You only need it to execute code.

    So, even when no code is actually executed in parallel, you still cut down the overall execution time, allowing other code to run while waiting.

June 21, 2025 Score: 2 Rep: 56 Quality: Low Completeness: 60%

Indeed, you can also test this adding some timers and some prints. Just for your curiosity.

val currentWeather = async { getCurrentData() }.await() trigger and wait
then 
val forecastWeather = async { getForecastData() }.await() trigger and wait 

vs

val currentWeather = async { getCurrentData() }  trigger
instant goes to the next instruction
val forecastWeather = async { getForecastData() } trigger

// then wait for both at the same time

If these are let's say some http requests that were taking 0.5 seconds, you just saved a half of a second. Congrats!

In an ideal world you would not have to wait here.

WeatherHomeUiState.Success(Weather(currentWeather.await(), forecastWeather.await()))

but rather send an observable and let the UI directly wait for the response. While your thread goes on with it's work. This depends on your structure, I am not familiar with Kotlin.
The idea would be pushing the Observable as close to your interface as you can. For example in typescript we have something like this.

offers$ being an Observable, in this case the html, the interface is the one waiting for the answer, the typescript is just passing the Observable reference.