我正在学习Kotlin协程。我已经读过runBlocking是桥接同步和异步代码的方法。但是,如果runBlocking停止UI线程,性能会提高多少?
例如,我需要在Android中查询数据库:

    val result: Int
    get() = runBlocking { queryDatabase().await() }

private fun queryDatabase(): Deferred<Int> {
    return async {
        var cursor: Cursor? = null
        var queryResult: Int = 0
        val sqlQuery = "SELECT COUNT(ID) FROM TABLE..."
        try {
            cursor = getHelper().readableDatabase.query(sqlQuery)
            cursor?.moveToFirst()
            queryResult = cursor?.getInt(0) ?: 0
        } catch (e: Exception) {
            Log.e(TAG, e.localizedMessage)
        } finally {
            cursor?.close()
        }
        return@async queryResult
    }
}

查询数据库将停止主线程,因此似乎花费的时间与同步代码相同?如果我缺少某些东西,请纠正我。

最佳答案

实际上,您使用 runBlocking 来调用“阻塞”代码中的挂起函数,否则将无法在那里调用它们,或者换句话说:您使用它来在协程上下文之外调用suspend函数(在您的示例中,传递给async的块是suspend功能)。同样(更明显的是,顾名思义,顾名思义),该调用也是阻塞调用。因此,在您的示例中,它的执行就像没有async一样。它等待(可中断地阻塞),直到runBlocking -block中的所有内容都完成为止。

例如,假设您的库中有一个函数,如下所示:

suspend fun demo() : Any = TODO()

该方法将无法从(例如)调用main。在这种情况下,您可以使用runBlocking,例如:
fun main(args: Array<String>) {
  // demo() // this alone wouldn't compile... Error:() Kotlin: Suspend function 'demo' should be called only from a coroutine or another suspend function
  // whereas the following works as intended:
  runBlocking {
    demo()
  } // it also waits until demo()-call is finished which wouldn't happen if you use launch
}

关于性能提升:实际上,您的应用程序可能宁愿响应速度更快,而不是性能更高(有时性能也更高,例如,如果您有多个并行操作而不是多个顺序操作)。但是,在您的示例中,分配变量时您已经阻塞了,因此我想说您的应用程序还没有变得更加响应。您可能希望异步调用查询,然后在响应可用后立即更新UI。因此,您基本上只是省略runBlocking,而是使用类似launch的东西。您可能也对Guide to UI programming with coroutines感兴趣。

08-26 01:32