【问题标题】:How to access class methods from anonymous suspend function inside constructor in kotlin?如何从kotlin构造函数中的匿名挂起函数访问类方法?
【发布时间】:2021-12-20 00:38:40
【问题描述】:

我希望能够在以下示例中从匿名构造函数的挂起函数中调用函数:

data class SuspendableStep(
    val condition: SuspendableCondition, 
    val continuation: Continuation<Unit>
)
class WaitCondition(cycles: Int) : SuspendableCondition() {

    private val timer = SomeTimer(cycles)

    override fun resume(): Boolean = timer.elapsed() // timer is handled somewhere else

    override fun toString(): String = "WaitCondition_$timer"
}
class BasicContinuation : Continuation<Unit> {

    var coroutine: Continuation<Unit>
    override val context: CoroutineContext = EmptyCoroutineContext
    private var nextStep: SuspendableStep? = null

    constructor(task: suspend () -> Unit) {
        coroutine = task.createCoroutine(completion = this)
    }

    override fun resumeWith(result: Result<Unit>) {
        nextStep = null
        result.exceptionOrNull()?.let { e -> Logger.handle("Error with plugin!", e) }
    }

    suspend fun wait(cycles: Int): Unit = suspendCoroutine {
        check(cycles > 0) { "Wait cycles must be greater than 0." }
        nextStep = SuspendableStep(WaitCondition(cycles), it)
    }

}
fun main() {
    BasicContinuation({
        println("HELLO")
        wait(1)
        println("WORLD")
    }).coroutine.resume(Unit)
}

我发现唯一的其他选择是通过创建匿名内部类并调用另一个函数来设置协程来覆盖挂起函数:

fun main() {
    val bc = BasicContinuation() {
        override suspend fun test() : Unit {
            println("HELLO")
            wait(1)
            println("WORLD")   
        }
    }
    bc.set() // assign coroutine to suspend { test }.createCoroutine(completion = this)
    bc.coroutine.resume(Unit)
}

【问题讨论】:

  • 您是否尝试在协程之上重新实现协程?看起来很奇怪。
  • 不,我只是希望能够访问我将多次重复使用的快捷实用程序方法来暂停协程。
  • 好吧,我不知道你的具体情况,我知道我的问题在这里有点离题。但是将您的实用程序创建为常规挂起功能还不够吗?例如:suspend fun wait(cycles: Int)。然后您可以将其用作任何其他挂起功能,而无需任何延续巫术。
  • 我需要协程来暂停活动任务的执行。挂起等待功能不起作用,因为您必须在其中定义要等待多长时间。我希望能够自己使用游戏刻度来计算它(刻度并不总是相同的长度,具体取决于很多因素)。另外,您必须在要使用它的每个类中声明它,因为如果没有我在答案中添加的 CoroutineScope,您将无法在 BasicContinuation 中访问它。

标签: kotlin kotlin-coroutines


【解决方案1】:

我使用 CoroutineScope 来扩展我可以访问的函数的范围:

class BasicContinuation : Continuation<Unit> {

    var coroutine: Continuation<Unit>
    override val context: CoroutineContext = EmptyCoroutineContext
    private var nextStep: SuspendableStep? = null

    constructor(task: (suspend BasicContinuation.(CoroutineScope) -> Unit)) {
        coroutine = suspend { task.invoke(this, CoroutineScope(context)) }.createCoroutine(completion = this)
    }

    override fun resumeWith(result: Result<Unit>) {
        nextStep = null
        result.exceptionOrNull()?.let { e -> Logger.handle("Error with plugin!", e) }
    }

    suspend fun wait(cycles: Int): Unit = suspendCoroutine {
        check(cycles > 0) { "Wait cycles must be greater than 0." }
        nextStep = SuspendableStep(WaitCondition(cycles), it)
    }

}
fun main() {
    val bc = BasicContinuation({
        println("Hello")
        wait(1)
        println("World")
    })
    bc.coroutine.resume(Unit) // print "Hello"
    // increment timer
    bc.coroutine.resume(Unit) // print "World
}

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 2015-05-04
    • 2017-02-13
    • 2023-03-26
    相关资源
    最近更新 更多