I am creating a coroutine using the script below:
fun bar(completion: () -> Unit) { GlobalScope.launch(Dispatchers.IO) { val lambda = { withContext(Dispatchers.Main) { //Suspension functions can be called only within coroutine body completion() } } foo(lambda) } } fun foo(lambda: () -> Unit) { //...do something heavy lambda() }
But I am getting the error Suspension functions can be called only within coroutine body
when I call withContext(Dispatchers.Main)
because the lambda changes the context. I cannot change foo(lambda: () -> Unit)
to foo(lambda: suspend () -> Unit)
because it's from an external library.
Any idea of what I can do to call withContext(Dispatchers.Main)
inside the lambda created inside the launch
context?
Thank you!
With coroutines, it just suspends and gives the library a continuation with the instruction "Once you've got this data, just send it to the resume function". Then the thread can go do other things. Once the data is there, the thread will be used to resume from the point where the coroutine was suspended.
delay is a special suspending function. It suspends the coroutine for a specific time. Suspending a coroutine does not block the underlying thread, but allows other coroutines to run and use the underlying thread for their code.
The syntax of a suspending function is similar to that of a regular function except for the addition of the suspend keyword. It can take a parameter and have a return type. However, suspending functions can only be invoked by another suspending function or within a coroutine.
We just have to use the suspend keyword. Note: Suspend functions are only allowed to be called from a coroutine or another suspend function. You can see that the async function which includes the keyword suspend. So, in order to use that, we need to make our function suspend too.
You can rewrite your bar
function like this:
fun bar(completion: () -> Unit) { GlobalScope.launch(Dispatchers.IO) { suspendCoroutine<Unit> { val lambda = { it.resume(Unit) } foo(lambda) } withContext(Dispatchers.Main) { completion() } } }
fun bar(completion: suspend CoroutineScope.() -> Unit) { GlobalScope.launch(Dispatchers.IO) { val lambda : suspend CoroutineScope.() -> Unit = { withContext(Dispatchers.Main) { //Suspension functions can be called only within coroutine body completion() } } foo(this,lambda) } } private suspend fun foo( coroutineScope: CoroutineScope , lambda : suspend CoroutineScope.() -> Unit) { lambda.invoke(coroutineScope) }
also like this
fun bar(completion: suspend CoroutineScope.() -> Unit) { GlobalScope.launch(Dispatchers.IO) { foo(this){ withContext(Dispatchers.Main) { //Suspension functions can be called only within coroutine body completion() } } } } private suspend fun foo( coroutineScope: CoroutineScope , lambda : suspend CoroutineScope.() -> Unit) { lambda.invoke(coroutineScope) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With