I have a question regarding if I can get into any ...
# coroutines
s
I have a question regarding if I can get into any “trouble” using async in this context (Using async to do 2 stuff in parallel to not unnecessarily wait for some network request). I am always unsure about how cancellations etc. are handled so I am posting this question here, more in thread🧵
I have two alternative ways of writing this one function #1
Copy code
viewModelScope.launch {
    val someBooleanResult = async { someService.someFlow().firstOrNull() ?: false }
    val someModel = someSuspendingUseCase()
    val result = someModel.copy(someBoolean = someBooleanResult.await())
    // do something with result
}
#2
Copy code
viewModelScope.launch {
    val someBooleanResult = someService.someFlow().firstOrNull() ?: false
    val someModel = someSuspendingUseCase()
    val result = someModel.copy(someBoolean = someBooleanResult.await())
    // do something with result
}
With the difference being that I am wrapping the someBooleanResult in an async function or not. Let’s assume that both of these may take ~3 seconds each, meaning that I don’t want to wait for 6 seconds for no reason, I’d prefer to wait 3 seconds with them being done in parallel. My thought process is that since
someSuspendingUseCase
and
someService.someFlow().firstOrNull()
don’t rely on each other, I could run them in parallel by making the first one as async, so that
someSuspendingUseCase
doesn’t need to wait for the first suspending function to be done before it starts fetching. Now I’ve seen many examples of how using async can potentially not be safe, breaking structured concurrency or whatnot, but I am afraid I don’t quite understand all the details of it. So in short, how safe is it to go with #1 to make them both run in parallel, what problems am I opening myself to?
n
Absolutely go for
async
that is why
async
was designed for. If you have any other code in between you can use
async
for the
someSuspendinUseCase
too. Just make sure you get off of the main thread to get concurrency. I think the dispatcher of
viewModelScope
is
Dispatchers.Main
so you have to change thread in your flow and the other suspend function only if you are not using a library that does that for you. Any
async
or
lunch
fired under the
viewModelScope
would be the children of the
viewModelScope
so when it get cancelled, child processes would be cancelled too.
e
there is danger if you use
GlobalScope.async
- but as Nilanjan says,
viewModelScope.async
(or anything else launched from any other coroutine scope launched from
viewModelScope
) is safe. if you're going to be calling into any blocking code, be sure to switch dispatchers to get off the main thread (e.g.
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
within the flow/usecase)
s
Awesome that’s very nice to hear! I am staying away from GlobalScope anyway, so I suppose I shouldn’t worry about it too much.
👍 1