2017-06-12 42 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中瞭解有關使用協程的各種方法的更多信息。