我正在学习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感兴趣。