kotlin协程和主要处理程序的关系

我有以下片段

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") } } 

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

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

但是奇怪的事情发生了,在20000毫秒的时间内,即使我点击后释放按钮,按钮仍然保持按下的状态 ,然后当onClick方法结束时,我意识到按下的状态被恢复,

我有一个原始的概念,协程是使用CPS将代码转换为回调样式函数的编译器魔术

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

所以我有以下问题

  1. 到底是谁和什么时候实际调用回调函数(例如trace(“blocking end”)),如果答案是主要的活套或者什么的(对于nodejs,可能是eventloop),我们应该调整协程的框架,让coroutine把事件到队列?
  2. 说协程实际上是编译器的魔法,我们可以写上面的代码,它不会触发一个ANR,但保持20000L的状态?

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

您可以用launch(UI)替换runBlocking来在UI线程上启动后台协程,而不会阻塞UI线程。 您可以在“kotlinx.coroutines指南”和“使用协程的UI编程指南”中了解有关使用协程的各种方法的更多信息。