【发布时间】: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 ")})
所以我有以下问题
- 到底谁和何时实际调用回调(例如trace("blocking end")),如果答案是主循环器或其他东西(对于nodejs,可能是事件循环),我们是否应该为协程调整框架并让协程将事件放入队列?
- 说协程其实就是编译器魔法,我们能不能写和上面的sn-p一样的代码,不触发ANR但保持20000L的按下状态?
【问题讨论】:
-
看起来你做了很多你不需要做的假设。对
runBlocking的调用创建了一个在调用它的同一线程上运行的协程,并在暂停点上阻塞线程。因此,对delay的调用只会阻塞运行onClick函数的线程。 -
不清楚你想要达到什么目的。 @marstran 解释了当前行为。您不应从 UI 线程调用
delay和runBlocking。通过调用launch(CommonPool)将其转移到其他线程,或者不调用delay。
标签: android kotlin coroutine anko