2017-06-12 51 views
2

我在下面的代码片断科特林协程和主处理程序关系

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之后出现#3并且没有ANR对话框显示

但是在20000毫秒,按钮按住按下状态甚至当我松开按钮后点击右键,然后我意识到按下状态恢复时的onClick方法结束,

我有一个原始的概念, 协程是利用CPS的编译器魔术转换的代码放到一个回调函数风格像遵循

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

,所以我有谁当实际调用回调函数(如跟踪(“堵月底结束下列问题

  1. “))如果答案是主要的looper或者什么(对于nodejs,可能是eventloop),我们是否应该调整协程的框架,让coroutine把事件放到队列中?
  2. 说协程实际上是编译器的魔力,我们可以写上相同的代码作为上面不触发ANR,但保持20000L按下状态的片段吗?
+2

看来你正在做出很多假设,你并不需要做出。对'runBlocking'的调用创建一个协调程序,该协程运行在它所调用的同一线程上,并在挂起点上阻塞该线程。因此,对'delay'的调用会阻止'onClick'函数运行的线程。 – marstran

+0

你不清楚你想达到什么目的。当前行为由@marstran解释。您不应该在UI线程中将'delay'与'runBlocking'结合起来使用。通过调用'launch(CommonPool)'或者不要调用'delay',将其转移到其他线程。 – xap4o

回答

3

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

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