【问题标题】:kotlin coroutine and main handler relationshipkotlin协程和主处理器的关系
【发布时间】:2017-06-12 11:48:24
【问题描述】:

我有以下 sn-p

 verticalLayout {
        gravity = Gravity.CENTER
        button("BUTTON").onClick {
            trace("click on process")
            runBlocking {
                trace("blocking start") // #1
                delay(20000L)  #2
                trace("blocking end")  // #3
            }
            trace("click process end")
        }
    }

trace 是一个定义为实用函数的函数,用于使用带有当前线程名称的 Log.e 注销消息

当我单击按钮时,所有代码都按预期运行,并且日志显示所有跟踪函数都在主线程中调用 #3 的日志出现在 #1 之后 20000L 毫秒内,并且没有显示 ANR 对话框

但奇怪的事情发生了,在 20000L ms 期间,即使我在单击后立即释放按钮,按钮仍保持 按下状态,然后我意识到当 onClick 方法结束时恢复按下状态,

我有一个原始概念 coroutine 是一种编译器魔法,使用 CPS 将代码转换为回调风格的函数,如 follow

delay(20000L,callback = { trace("blocking end ")})

所以我有以下问题

  1. 到底谁和何时实际调用回调(例如trace("blocking end")),如果答案是主循环器或其他东西(对于nodejs,可能是事件循环),我们是否应该为协程调整框架并让协程将事件放入队列?
  2. 说协程其实就是编译器魔法,我们能不能写和上面的sn-p一样的代码,不触发ANR但保持20000L的按下状态?

【问题讨论】:

  • 看起来你做了很多你不需要做的假设。对runBlocking 的调用创建了一个在调用它的同一线程上运行的协程,并在暂停点上阻塞线程。因此,对delay 的调用只会阻塞运行onClick 函数的线程。
  • 不清楚你想要达到什么目的。 @marstran 解释了当前行为。您不应从 UI 线程调用 delayrunBlocking。通过调用launch(CommonPool) 将其转移到其他线程,或者不调用delay

标签: android kotlin coroutine anko


【解决方案1】:

您正在使用runBlocking,它以这种方式命名,因为它在协程执行期间阻塞了调用它的线程。在您的特定情况下,您正在使用runBlocking 阻塞您的 UI 线程。

您可以将runBlocking 替换为launch(UI) 以在UI 线程上启动后台协程,而不会阻塞UI 线程。您可以在 Guide to kotlinx.coroutinesGuide to UI programming with coroutines 中了解有关使用协程的各种方法的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 2019-06-02
    • 2019-04-13
    • 1970-01-01
    • 2022-07-25
    • 2020-01-10
    • 2021-05-21
    • 1970-01-01
    相关资源
    最近更新 更多