Can this be simplified?
# coroutines
r
Can this be simplified?
I’m having a heck of a time understanding which `suspend`s are running on which contexts. Essentially, I need to jump off to
IO
for anything in
Bar
, but I need the
action
arg for
getAThing
to have its body defaulted to
Main
and have every
suspend
in it suspended to
IO
.
l
Yes, no code is shorter. Sorry for the unhelpful response, but I fail to see any clue on what you want to achieve, and
foo
and
bar
are not helping much. Some observations regarding your snippet still: It seems there's no reason
Bar
should implement
CoroutineScope
. The
async
block in
getAThing
is code smell. It breaks structured concurrency as it doesn't use a local scope and its result is not used. Please, read
async
doc and understand that you rarely need it.
r
Ok, to give some context,
Foo
is a presenter-type object and it needs to invoke view actions on the main thread.
Bar
is a repository-type object. It needs to make network requests and db queries via the appropriate interfaces. Those kinds of transactions have to happen off the main thread. Some network objects need additional network requests made in order coalesce multiple data sources. I need the original result immediately displayed to the screen and continue to resolve the extra requests in the background, invoking view updates using
action
. I’m using
async
to force the extra calls to be made asynchronously.
made some changes to the example to try to make it more clear
l
Why not rename Foo and Bar too to something more meaningful?
r
Renamed. Hopefully that helps
l
What is
action
supposed to do?
r
I pass it in in the
doWork
fun in
Presenter
I’m using it to update the view in response to the result of
updateThing
l
You can just drop that lambda and update the view after calling the suspending function
r
I won’t have the reference to the new
Thing
type object
and if I have 100 `Thing`s to update, I don’t want to wait for all of them to resolve to update the view
@louiscad Thanks for the tip about removing
CoroutineScope
from
Repository
. That actually helped me understand a lot better. I reorganized the code a bit to just invoke
updateThing
from
doWork
and pass in the updates there at the end of the block.
I think I understand where I went wrong in organizing everything
b
I'd probably recommend
val thing = db.getThing() ?: network.getThing()
instead of
var thing ...
r
The
network.getThing()
portion is vastly over simplified in this example. I was hoping to get more input on the way I've organized coroutines in this example.
👍 1
u
Can you just return the updated thing? Then just use the return value instead of a call back?
⏸️ 1
1
r
@uli
Thing
is a list that can have hundreds of entries and
updateThing
has to do a network call for each thing. I want the view to be updated as each entry is resolved, rather than wait for potentially hundreds of network calls to resolve.
u
But this is not what your code does. It calculates the full update and only then passes it as parameter to
action
If you want to stream results take a look at channel or flow
r
@uli You’re right, I changed it to reflect what the codebase actually performs. Do you recommend that I pass the channel in that I would publish to?
u
You could, but why do you return
thing
from all methods. In the end the return value seem unused. Instead you could return a freshly created channel.
l
Or return a Flow
r
unfortunately this is a production application and I can’t risk implementing preview features in it