Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在suspendCoroutine块内调用挂起函数的适当方式是什么?_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android 在suspendCoroutine块内调用挂起函数的适当方式是什么?

Android 在suspendCoroutine块内调用挂起函数的适当方式是什么?,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,在调用continuation.resume()之前,我需要在suspendCoroutine块中调用挂起函数。 这样做的适当方式是什么 private suspend fun someFunction()=suspendCoroutine{cont-> //... val myResult=mySuspendingFunction()//不能在块中调用suspend函数,因为它接受非挂起块作为参数: suspend inline fun <T> suspendCoroutine(

在调用
continuation.resume()
之前,我需要在
suspendCoroutine
块中调用挂起函数。 这样做的适当方式是什么

private suspend fun someFunction()=suspendCoroutine{cont->
//...

val myResult=mySuspendingFunction()//不能在块中调用
suspend
函数,因为它接受非挂起块作为参数:

suspend inline fun <T> suspendCoroutine(
    crossinline block: (Continuation<T>) -> Unit
): T
如果function
someFunction()
没有通过回调调用Api,那么您应该重新考虑摆脱“SuspendCorroutine”的方法:

private suspend fun someFunction() {
    // ...
    val myResult = mySuspendingFunction()
    // ...
}

如果仍要使用
suspendCoroutine
mySuspendingFunction
的调用移出
suspendCoroutine
块:

private suspend fun someFunction(): String {
    val myResult = mySuspendingFunction()

    return suspendCoroutine { cont ->
        //...
        cont.resume(myResult)
    }
}

suspend fun mySuspendingFunction(): String {
    delay(1000) // simulate request
    return "result"
}

最好避免这种情况,并在
SuspendCorroutine
之前调用suspendCorroutine函数,正如其他人所回答的那样。这对于所讨论的特定情况是可能的

但是,如果您需要继续,这是不可能的

(以下是针对那些因为这个原因而发现这个问题的人,比如@Zordid和我。
chan.send
就是一个例子。)

在这种情况下,以下是一种可能的、但容易出错的方法,我不推荐:

suspend fun cont1(){
//顺便说一句,为了正确实现,这应该至少是SuspendCancelableCorroutine
suspendCoroutine{uCont->
val x=suspend{chan.send(foo(uCont))}
x、 Start例程(延续(uCont.context){
如果(it.isFailure)
uCont.resumeWith(it)
//否则就由成龙的话继续
})
}
}
(我认为错误处理本身就说明了为什么它不是一个很好的选择,尽管存在其他问题。)

一种更好、更安全、更便宜的方法是尽可能使用
CompletableDeferred

如果您必须通过续读,则这样做更安全,而且可能更便宜:

suspend fun cont2(){
val rslt=CompletableDeferred()
chan.send(foo(Continuation(currentCoroutineContext()){
rslt.完成(it)
}))
rslt.wait()
}

为什么要将它包装在
SuspendCorroutine中?
SuspendCorroutine
是一个低级包装器,您实际上应该只使用它包装非Corroutine异步api。您没有理由需要从中调用挂起函数。
SuspendCorroutine
调用包装基于回调的api调用。de>mySuspendingFunction
调用在其中一个回调中。是的,
suspendCoroutine
调用正在包装一个基于回调的api调用。对
mySuspendingFunction
的调用在其中一个回调中。我想象调用
CoroutineScope()。启动{}
inside
suspendCoroutine
会很糟糕,对吧?我想这不是个好主意。为什么不在
someFunction
之前或之后调用
mySuspendingFunction
?我会的。谢谢你的帮助!我也有同样的问题。我有一个很好的理由无法重新排序执行。我想构建一个susKafka的Producer.send(data,callback)调用的pend函数。这一切看起来都很好,而且工作正常——有点像。结果证明,Kafka提供的send方法同时是异步的和阻塞的。设计很糟糕!所以我想用RunInterruptable{Producer.send(data,callback)}调用它-但我只能在SuspendCancelableCorroutine中执行此操作,因为要构建回调,我确实需要继续。之前无法执行…:-(这是一个非常糟糕的情况。。。
private suspend fun someFunction(): String {
    val myResult = mySuspendingFunction()

    return suspendCoroutine { cont ->
        //...
        cont.resume(myResult)
    }
}

suspend fun mySuspendingFunction(): String {
    delay(1000) // simulate request
    return "result"
}