Kotlin 协程`runBlocking` [英] Kotlin coroutines `runBlocking`

查看:69
本文介绍了Kotlin 协程`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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆