2017-06-12 2 views
2

Je rencontre l'extrait suivantKotlin coroutine et principal gestionnaire relation

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 est une fonction définie comme une fonction d'utilité pour se déconnecter des messages en utilisant Log.e avec le nom de thread courant

lorsque i cliquez sur le bouton, tout le code fonctionne comme prévu et les journaux montrent toutes les fonctions de trace sont appelées dans le thread principal log pour # 3 apparaît après # 1 dans 20000L ms et aucune boîte de dialogue ANR affiche

mais des choses étranges se sont produites, au cours de 20000L ms , le bouton maintenir l'état pressé même quand je relâchez le bouton droit après clic, puis je pris conscience de l'état pressé est restauré à la fin méthode onClick,

i avait un concept cru que coroutine est une magie du compilateur en utilisant CPS à transformer le code en fonction de style de rappel comme suivre

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

donc j'ai les questions suivantes

  1. à la fin qui appelle et quand en fait le rappel (par exemple trace ("extrémité de blocage ")) si la réponse est le looper principal ou quelque chose (pour nodejs, peut-être le eventloop), devons-nous adapter le cadre de coroutine et laisser le coroutine mettre l'événement dans la file d'attente?
  2. en disant que coroutine est en fait de la magie du compilateur, pouvons-nous écrire le même code que l'extrait ci-dessus qui ne déclenche pas un ANR mais maintient l'état pressé pour 20000L?
+2

Il semble que vous fassiez beaucoup de suppositions que vous n'avez pas vraiment à faire. L'appel à 'runBlocking' crée un coroutine qui s'exécute sur le même thread que celui sur lequel il est appelé, et bloque le thread sur les points de suspension. L'appel à 'delay' bloque donc simplement le thread sur lequel s'exécute la fonction' onClick'. – marstran

+0

On ne sait pas ce que vous essayez d'atteindre. Le comportement actuel est expliqué par @marstran. Vous ne devriez pas appeler 'delay' en combinaison avec' runBlocking' du thread UI. Vous pouvez le déplacer vers un autre thread en appelant 'launch (CommonPool)' ou n'appelez pas 'delay'. – xap4o

Répondre

3

Vous utilisez runBlocking qui est nommé ainsi car il bloque le thread sur lequel il est appelé pendant la durée de l'exécution de la corbeille. Dans votre cas particulier, vous bloquez votre thread d'interface utilisateur avec runBlocking.

Vous pouvez remplacer runBlocking par launch(UI) pour démarrer une coroutine d'arrière-plan sur le fil d'interface utilisateur sans bloquer le fil d'interface utilisateur. Vous pouvez en apprendre plus sur les différentes façons de travailler avec les coroutines dans le et dans le Guide to UI programming with coroutines.