Nat Strangerweather
10/26/2022, 4:57 PMfunction1 ()
and function2 ()
into suspend functions, and set them up like this:
val scope = rememberCoroutineScope()
ElevatedButton(
onClick = {
scope.launch {
function1 ()
function2 ()
}
},
The problem is that I need for function1 to be completed before function2 can start. So if I put a 1 second delay between the two, my app works as expected, but if I don't it seems function2 does not wait for function1 to complete before it starts. Is there a way to get f1 to finish before f2 starts without adding a delay in between the two?Casey Brooks
10/26/2022, 5:09 PMsuspend
functions sequentially is how coroutines work by nature. A function marked suspend
will run and “suspend execution” until it completes and that function returns. So in your example, until function1()
returns, function2()
will not start.
But how those functions are internally implemented may affect that behavior. Just because a function is marked suspend
doesn’t necessarily mean that it actually will suspend execution and wait for it to complete. For example, if each of those functions calls launch { }
, then they will return immediately and be running in parallel instead of in series, even if the functions are marked suspend. Basically, suspend
doesn’t do anything on its own to make sure things are running in series or in parallel, it just opens up the possibility for you to do that yourself.
Can you paste the implementation of your function1
and function2`? It’s difficult to know why it’s not behaving correctly without knowing how you have those functions implementedNat Strangerweather
10/26/2022, 5:19 PMsuspend fun interruptionFilterAll() {
notificationManager.setInterruptionFilter(
NotificationManager.INTERRUPTION_FILTER_ALL
)
}
and function2 is this:
suspend fun interruptionFilterPriority() {
notificationManager.setInterruptionFilter(
NotificationManager.INTERRUPTION_FILTER_PRIORITY
)
}
I have a series of options that look like this:
val option3 = Option(
title = "PRIORITY ONLY",
function = { scope.launch { filterFun.interruptionFilterPriority() } },
icon = Icons.Filled.Star,
selected = selected,
enabled = enabled,
id = 2
)
val option4 = Option(
title = "DND OFF",
function = { scope.launch { filterFun.interruptionFilterAll() } },
icon = Icons.Filled.DoNotDisturbOff,
selected = selected,
enabled = enabled,
id = 3
)
And eventually I call the functions as shown above. I now realise that I am launching each function twice. Maybe that's the problem...Nat Strangerweather
10/26/2022, 5:20 PMElevatedButton(
onClick = {
scope.launch {
filterFun.interruptionFilterAll()
delay(1000L)
option.function()
}
},
Casey Brooks
10/26/2022, 5:31 PMsuspend
. I think this is causing you some confusion. The main problem is that you’re calling launch
within a launch
, but the coroutine scopes of the two launch
blocks are not connected to each other, so it’s breaking the concept of “structured concurrency”.
You have ElevatedButton
launch a coroutine, which calls option.function()
which is not marked with suspend
. So when the implementation of option.function()
calls launch
within itself, it’s just running in a completely separate coroutine, with no relation to the block within ElevatedButton
. What you would typically do instead is make your function
lambda suspend ()->Unit
instead so that it can call other suspend functions, but within the CoroutineScope of ElevatedButton
. But as I mentioned at the beginning, in this specific case, you shouldn’t need to mark anything suspend
at all, because it’s really not doing anything for you and is just making things more confusingNat Strangerweather
10/26/2022, 5:35 PMNat Strangerweather
10/26/2022, 5:38 PM