如何在Kotlin中返回等待的值?

时间:2018-11-21 14:47:42

标签: kotlin async-await kotlin-coroutines

我需要test()才能从我的数据库中返回一名玩家。我知道我可以使用回调,但是如何使用async await来做到这一点?

fun test(): Player {
    launch(UI) {
        val player = async(CommonPool) { MainActivity.database?.playerDao()!!.loadPlayer() }.await()
        return player
    }
}

当前错误为return is not allowed here

例如,在JavaScript中,我将使test async然后await来自调用位置。

1 个答案:

答案 0 :(得分:4)

不可能在原始线程上运行协程。至少必须将现有线程转换为可旋转顶级事件循环的线程。您可以通过在线程的调用堆栈的顶部(即,在其runBlocking方法内部)进行run()调用来实现此目的。

在GUI线程或运行事件循环的任何其他类型的线程上,您需要一个匹配的Dispatcher来向该事件循环提交协程。 Kotlin已经为Swing,JavaFX,Android等提供了调度程序。在这些情况下,您需要从一些现有的GUI事件处理程序中launch协程,例如:

myScope.launch {
    val player = test()
    ... use the player ...
}

myScope必须是使用以下内容实现CoroutineScope的对象:

override val coroutineContext = Dispatchers.Main + SupervisorJob()

这将为您提供一种方法,通过调用来完全取消在同一范围内运行的所有协程

coroutineContext[Job]!!.cancel()

我的示例使用Main调度程序,当您导入与UI框架匹配的Kotlin协程库时,该调度程序解析为GUI线程。

test()函数必须成为suspend fun,该临时将调度程序临时切换到线程池以进行阻塞操作。这是一个基本示例的外观:

suspend fun test() = withContext(Dispatchers.IO) {
    MainActivity.database?.playerDao()!!.loadPlayer()
}

最后,请注意,在此答案中我根本没有提到async。 Kotlin的async有一个非常特定的目的,它不是像其他语言那样的通用工具。其目的是严格并行分解,将单个任务分解为多个并发子任务。