Kotlin 协程`runBlocking` [英] Kotlin coroutines `runBlocking`
问题描述
我正在学习 Kotlin 协程.我读过 runBlocking
是桥接同步和异步代码的方法.但是,如果 runBlocking
停止 UI 线程,性能增益是多少?比如我需要在Android中查询一个数据库:
I am learning Kotlin coroutines. I've read that runBlocking
is the way to bridge synchronous and asynchronous code. But what is the performance gain if the runBlocking
stops the UI thread?
For example, I need to query a database in 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
}
}
查询数据库会停止主线程,所以看起来和同步代码需要一样多的时间?如果我遗漏了什么,请纠正我.
Querying the database would stop the main thread, so it seems that it would take the same amount of time as synchronous code? Please correct me if I am missing something.
推荐答案
其实你用的是 runBlocking
在阻塞"代码中调用挂起函数,否则这些函数在那里是不可调用的,或者换句话说:你使用它在协程上下文之外调用 suspend
函数(在您的示例中,传递给 async
的块是 suspend
函数).此外(更明显,正如名称本身所暗示的那样),该调用是一个阻塞调用.因此,在您的示例中,它的执行就像没有像 async
这样的东西到位.它等待(可中断地阻塞)直到 runBlocking
-block 中的所有内容都完成.
Actually you use runBlocking
to call suspending functions in "blocking" code that otherwise wouldn't be callable there or in other words: you use it to call suspend
functions outside of the coroutine context (in your example the block passed to async
is the suspend
function). Also (more obvious, as the name itself implies already), the call then is a blocking call. So in your example it is executed as if there wasn't something like async
in place. It waits (blocks interruptibly) until everything within the runBlocking
-block is finished.
例如假设您的库中有一个函数如下:
For example assume a function in your library as follows:
suspend fun demo() : Any = TODO()
这个方法不能被调用,例如<代码>主要代码>.对于这种情况,您可以使用 runBlocking
然后,例如:
This method would not be callable from, e.g. main
. For such a case you use runBlocking
then, e.g.:
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
的东西.您可能还对 UI 编程指南感兴趣协程.
Regarding performance gain: actually your application may rather be more responsive instead of being more performant (sometimes also more performant, e.g. if you have multiple parallel actions instead of several sequential ones). In your example however you already block when you assign the variable, so I would say that your app doesn't get more responsive yet. You may rather want to call your query asynchronously and then update the UI as soon as the response is available. So you basically just omit runBlocking
and rather use something like launch
. You may also be interested in Guide to UI programming with coroutines.
这篇关于Kotlin 协程`runBlocking`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!