https://kotlinlang.org logo
Title
n

Noel Stieglitz

03/31/2021, 7:28 PM
Hi Everyone! I have a question that straddles the Android/coroutine slack channels, but I think the heart of the question is about structured concurrency. I'm working on an Android app that has a ViewModel that references a repository. The repository exposes a method that makes two concurrent API calls and returns the result of both after both have finished. What I have now is something like this:
suspend fun fetchTwoThings(): TheResultsModel =
            coroutineScope {
                val job1 = getStuff1(this) // both of these functions use the passed in coroutine scope like scope.async(<http://Dispatchers.IO|Dispatchers.IO>) { ... API call here }
                val job2 = getStuff2(this)
                awaitAll(job1, job2)

                return@coroutineScope TheResultsModel(
                        thing1 = job1.await(),
                        thing2 = job2.await()
            }
Is there any downside to using the
coroutineScope
like this in the repository? Alternatively, I could pass in the
viewModelScope
. Maybe that's ok since the ViewModel class instantiates the repo as a member variable. The lifetime of the repository is already tied to the ViewModel class. Yet another option is to expose
getStuff1
and
getStuff2
to the ViewModel, and manage the coroutine there. I'm not a huge fan of that since I might want to call
fetchTwoOtherThings
from other places and would have to duplicate that code. What are your thoughts? How can I do this better?
z

Zach Klippenstein (he/him) [MOD]

03/31/2021, 7:32 PM
This looks very idiomatic to me. I don’t see any downside as far as coroutines are concerned. Whether it makes sense to expose
fetchTwoThings
or
getStuffN
from your repository isn’t really a coroutines question, it depends more on what responsibilities are appropriate for your different architectural layers.
n

Noel Stieglitz

03/31/2021, 8:02 PM
Cool, thanks for your input. The only reason I’d expose
getStuffN
rather than
fetchTwoThings
is if there were some advantage specific to the coroutines. For instance if using the
viewModelScope
rather than using the
coroutineScope
builder were better, and it were not a good idea to pass
viewModelScope
down to the repository.
z

Zach Klippenstein (he/him) [MOD]

03/31/2021, 8:06 PM
no, this type of encapsulation is exactly what structured concurrency was designed for!
n

Noel Stieglitz

03/31/2021, 8:06 PM
excellent! thanks again
u

ursus

03/31/2021, 9:10 PM
why does repository need a scope like that? I'd make it just a suspend function, and launch it in viewmodel scope
👍 1
n

Noel Stieglitz

03/31/2021, 11:05 PM
It needs a coroutine so that
getStuff1
and
getStuff2
can run concurrently
z

Zach Klippenstein (he/him) [MOD]

03/31/2021, 11:21 PM
I’m not sure if this is what Vlastimil meant, but I would probably expose
getStuff1
and
getStuff2
as suspend funs, then in
fetchTwoThings
call them as
async { getStuff1() }
etc.
👍 1