Oleg Siboglov
03/30/2021, 11:19 PMsuspend fun foo(): Bar {
// I call another suspend function here returning an intermediate value.
if (error) {
suspendCancellableCoroutine<Bar> { continuation ->
val listener = object : Listener {
override fun callback() {
// I need to call this suspend function again.
// However, here is where I get an error.
continuation.resume(foo())
}
}
// I call other functions that will eventually call the listener.
}
}
}
The error that I get is obvious - Suspension functions can be called only within coroutine body
. However, I’m not really quite sure on how to resume the coroutine properly. Any help is much appreciated. Thank you.efemoney
03/31/2021, 12:11 AMcallback
runs on is not suspending so you cannot call suspending functions inside of it.
One thing you can do is use runBlocking
to wrap the inner foo
function. Whoever calls outer foo
is still suspended and when the inner runBlocking returns, outer foo’s caller should be resumed (as intended).
But you should also restructure your code. This is what it looks like to me:
class Bar
fun interface Listener {
fun callback()
}
suspend fun doIntermediateStuff(): Boolean = TODO()
suspend fun suspendForCallback() = suspendCancellableCoroutine<Unit> { continuation ->
val listener = Listener {
continuation.resume(Unit)
}
// someOtherCode.register(listener)
}
suspend fun foo(): Bar {
val isError = doIntermediateStuff()
if (isError) {
suspendForCallback()
return foo()
}
return Bar()
}
Casey Brooks
03/31/2021, 3:17 PMsuspendCancellableCoroutine
would be a callbackFlow
, which does allow suspending functions to be called within with blockuli
04/02/2021, 9:49 AM