This is from Google's sample. I'm particularly int...
# coroutines
f
This is from Google's sample. I'm particularly interested in the
_taskUpdatedEvent
, which triggers the back navigation in the fragment. They navigate back from the screen after the insert operation is finished. Isn't this pretty similar to blocking the UI thread? It won't freeze the UI, but you can't actually do anything on that screen until the operation is finished and it's not really necessary to not navigate back immediately. I know that this operation will only take a few milliseconds but still, there is a reason why we execute queries on a background thread in the first place. Also, this could take longer depending on what happens in the repository. What is your opinion? Edit:
createTask
and
updateTask
are suspending functions
s
Waiting until the insert is complete before navigating back ensures that the
viewModelScope
isn't canceled before it's complete. It's not the same as blocking the UI thread because the user won't experience an actually frozen screen (which is still frustrating even if you think there's nothing left on the screen) and they won't get an ANR prompt to close the app. If you are worried about the user thinking the app isn't doing anything while you wait for an action to finish, then you can present a loading indicator (e.g. use a pulltorefresh layout snd manually set its
refreshing
value). Also, waiting for the data layer to finish doing its thing gives you a chance to listen for errors (as a return value, for example) and display a failure to the user.
Also,
createTask
and
updateTask
aren't suspending functions. They are regular blocking functions that launch coroutines (which may be suspended) and then return a
Job
and
Unit
respectively. A suspending function must literally have the
suspend
modifier.
f
Right, I mean
saveTask
is a suspending function
And it doesn't actually freeze the UI, but it shows a UI that shouldn't be accessible anymore. If I delay the insert operation I can click the save button again (which inserts the entry twice)
would it be bad to execute the db operation in a wider coroutine scope and navigate back immediately?
s
Using a wider scope (probably an application level scope) would allow you to navigate back safely. This means you won't be able to communicate the result of the call to the user without extra work, though. One solution that is often used to prevent a double button press is to disable the button when it is pressed. You can re-enable it after an operation if necessary (which would probably mean launching your coroutine from
lifecycleScope
instead)
f
thanks
I always have to find a balance between doing it properly but also keeping it as simple as possible for my tutorials
navigating back immediately would make the app so much more simple than setting up a way to communicate back from the ViewModel to the fragment
I'm just not sure if it's really bad
or acceptable for a small app
instead of a wider scope I could also use
NonCancelable
. I know there are some warnings against but for a simple Room operation it should be fine
because if I navigate back immediately I could just use a return value from this method to decide between Snackbar and pop backstack
s
"acceptable for a small app" is a concerning phrase. A small app is only small until it's not. It's usually best to just do things properly from the beginning. As for the "simple Room operation", you shouldn't be making assumptions about the data layer at the viewmodel level. Maybe one day we add a remote call to save to some online source.
f
ok I see