Quelle est la relation entre Looper, Handler et MessageQueue dans Android?

j'ai vérifié la documentation officielle Android/guide pour Looper , Handler et MessageQueue . Mais je ne pouvais pas le faire. Je suis nouveau sur android, et est devenu très confus avec ces concepts.

82
demandé sur AnV 2012-10-14 03:29:01

5 réponses

a Looper est une boucle de traitement de messages: elle lit et traite des éléments à partir d'un MessageQueue . La classe Looper est habituellement utilisée en conjonction avec HandlerThread (une sous-classe de Thread ).

a Handler est une classe utilitaire qui facilite l'interaction avec un Looper - principalement en affichant des messages et des objets Runnable à le fil est MessageQueue . Lorsqu'un Handler est créé, il est lié à un Looper spécifique (et le thread associé et la file d'attente de message).

dans l'usage courant, vous créez et démarrez un HandlerThread , puis créez un Handler objet (ou objets) par lequel d'autres threads peuvent interagir avec l'instance HandlerThread . Le Handler doit être créé pendant l'exécution sur le HandlerThread , bien qu'une fois créé il n'y ait aucune restriction sur ce que les threads peuvent utiliser le Handler 's méthodes de planification ( post(Runnable) , etc.)

le fil principal (A. K. A. UI thread) dans une application Android est défini comme un thread handler avant que votre instance application ne soit créée.

en dehors de la classe docs, Il ya une belle discussion de tout cela ici .

92
répondu Ted Hopp 2017-03-31 19:58:12

il est largement connu qu'il est illégal de update UI components directement à partir de threads autre que main thread sous android. Ce document android ( Gérer les opérations coûteuses dans le fil UI ) suggère les étapes à suivre si nous avons besoin de démarrer un fil séparé pour faire certains travail coûteux et mettre à jour L'UI après qu'il est fait. L'idée est de créer un Gestionnaire objet associé avec fil conducteur , et après un Praticable au moment approprié. Ce Runnable sera invoqué sur le fil principal . Ce mécanisme est mis en œuvre avec les classes Looper et Handler .

Le Looper classe gère un MessageQueue , qui contient une liste de messages . Un caractère important de Looper est qu'il est associé avec le fil dans lequel le Looper est créé . Cette association est conservée pour toujours et ne peut être brisée ni changée. Notez également qu'un thread ne peut pas être associé à plus de un Looper . Afin de garantir cette association, Looper est stocké dans le stockage thread-local, et il ne peut pas être créé par l'intermédiaire de son constructeur directement. La seule façon de créer c'est appeler préparer méthode statique sur Looper . prepare méthode examine d'abord ThreadLocal de fil courant pour s'assurer qu'il n'y a pas déjà un Looper associé avec le fil. Après l'examen, un nouveau Looper est créé et enregistré dans ThreadLocal . Après avoir préparé le Looper , nous pouvons appeler boucle méthode sur elle pour vérifier messages et avoir Handler pour les traiter.

comme son nom l'indique, la classe Handler est principalement responsable du traitement (Ajout, Suppression, expédition) des messages du fil courant MessageQueue . Une instance Handler est aussi liée à un thread. La liaison entre le manipulateur et le fil est réalisée via Looper et MessageQueue . A Handler est toujours lié à a Looper , et par la suite lié au fil associé à avec le Looper . Contrairement à Looper , plusieurs instances de gestionnaire peuvent être liées au même thread. Chaque fois que nous appelons post ou n'importe quelle méthode semblable sur le Handler , un nouveau message est ajouté au MessageQueue associé . Le champ cible du message est Handler instance. Lorsque le Looper a reçu ce message, il invoque le dispatchMessage sur le champ cible du message, de sorte que le message renvoie à l'instance du gestionnaire à traiter, mais sur le thread correct. Les relations entre Looper , Handler et MessageQueue sont indiquées ci-dessous:

enter image description here

87
répondu K_Anas 2012-10-14 00:01:27

commençons par le Looper. Vous pouvez comprendre la relation entre Looper, Handler et MessageQueue plus facilement quand vous comprenez ce que Looper est. Aussi, vous pouvez mieux comprendre ce que Looper est dans le contexte de cadre GUI. Looper est fait pour faire 2 choses.

1) Looper transforme un fil normal , qui se termine lorsque sa run() méthode retourne, en quelque chose qui fonctionne en continu jusqu'à Android app est en cours d'exécution , qui est nécessaire dans le cadre GUI (techniquement, il se termine toujours lorsque la méthode run() retourne. Mais permettez-moi de clarifier ce que je veux dire, ci-dessous).

2) Looper fournit une file où les travaux à faire sont demandés, ce qui est également nécessaire dans le cadre de L'IGI.

Comme vous le savez peut-être, lorsqu'une application est lancée, le système crée un thread d'exécution pour l'application, nommée "main", et Android les applications tournent normalement entièrement sur un seul thread par défaut le "thread principal". Mais fil principal n'est pas quelque secret, fil spécial . C'est juste un thread normal que vous pouvez aussi créer avec le code new Thread() , ce qui signifie qu'il se termine quand sa méthode run() revient! Pensez à l'exemple ci-dessous.

public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}

maintenant, appliquons ce principe simple à L'application Android. Qu'arriverait-il si une application Android est exécuté sur un fil? Fil appelé "main" ou " UI " ou tout ce qui commence application, et tire toutes les UI. Ainsi, le premier écran est affiché aux utilisateurs. Alors quoi maintenant? Le fil principal se termine? Non, ça ne devrait pas. Ça devrait attendre que les utilisateurs fassent quelque chose, non? Mais comment parvenir à ce comportement? On peut essayer avec Object.wait() ou Thread.sleep() . Par exemple, le thread principal termine sa tâche initiale pour afficher le premier écran, et dort. Il se réveille, ce qui signifie interrompu, quand un nouveau travail à faire est trouvé. C'est très bien, mais à ce moment nous avons besoin d'une structure de données en file d'attente pour tenir plusieurs emplois. Que penser d'un cas lorsqu'un utilisateur touche l'écran en série, et une tâche prend plus de temps pour terminer. Nous avons donc besoin d'une structure de données pour effectuer les travaux de la manière du premier entré, premier sorti. En outre, vous pouvez imaginer, implémenter toujours-running-and-process-job-when-arrived thread en utilisant l'interruption n'est pas facile, et conduit à du code complexe et souvent impossible à maintenir. Nous préférerions créer un nouveau mécanisme à cette fin, et C'est ce que Looper est tout au sujet de . Le document officiel de la classe Looper dit, "les Threads par défaut n'ont pas une boucle de message associée à eux", et Looper est une classe "utilisé pour exécuter une boucle de message pour un thread". Maintenant tu peux comprendre ce que ça veut dire.

passons à Handler et MessageQueue. Tout d'abord, MessageQueue est la file d'attente que j'ai mentionné ci-dessus. Il réside à L'intérieur D'un Looper, et c'est tout. Vous pouvez vérifiez avec Looper's source code . Looper class a une variable membre de MessageQueue.

alors, Qu'est-ce que Handler? S'il y a une file d'attente, alors il devrait y avoir une méthode qui devrait nous permettre d'examiner une nouvelle tâche à la file d'attente, non? C'est ce Gestionnaire n'. Nous pouvons interroger une nouvelle tâche dans une file(MessageQueue) en utilisant diverses méthodes post(Runnable r) . C'est tout. Il s'agit de Looper, Handler, et MessageQueue.

Mon dernier mot est, donc essentiellement Looper est une classe qui est faite pour répondre à un problème qui se produit dans le cadre GUI. Mais ce genre de besoins peut également se produire dans d'autres situations. En fait, il s'agit d'un modèle assez célèbre pour l'application multi threads, et vous pouvez en apprendre plus à ce sujet dans "la programmation simultanée en Java" par Doug Lea(en particulier, chapitre 4.1.4 "worker Threads" serait utile). En outre, vous pouvez imaginer ce type de mécanisme n'est pas unique dans le cadre Android, mais tous les cadres GUI peut avoir besoin quelque peu semblable à cela. Vous pouvez trouver presque le même mécanisme dans Java Swing framework.

53
répondu 김준호 2017-10-30 06:55:10

MessageQueue : il s'agit d'une classe de bas niveau contenant la liste des messages à envoyer par un Looper . Les Messages ne sont pas ajoutés directement à un MessageQueue , mais plutôt par l'intermédiaire des objets Handler associés au Looper .[ 3 ]

Looper : il boucle sur un MessageQueue qui contient les messages à envoyer. La gestion de la file d'attente est assurée par le Handler qui est chargé de traitement (Ajout, Suppression, envoi) des messages dans la file d'attente des messages.[ 2 ]

Handler : il vous permet d'envoyer et de traiter des objets Message et Runnable associés à un thread MessageQueue . Chaque instance gestionnaire est associée à un seul thread et à la file d'attente de messages de ce thread.[ 4 ]

lorsque vous créez un nouveau Handler , il est lié au fil / à la file d'attente de messages le fil qui le crée -- à partir de ce point, il délivrera des messages et des runnables à cette file d'attente de message et les exécutera comme ils sortent de la file d'attente de message .

veuillez parcourir l'image ci-dessous[ 2 ] pour une meilleure compréhension.

enter image description here

22
répondu AnV 2016-05-01 13:39:33

MessageQueue, Handler, Looper in Android MessageQueue :

MessageQueue est une boucle de message ou une file d'attente de message qui contient essentiellement une liste de Messages ou de exécutables (ensemble de code exécutable).

en d'autres termes MessageQueue est une file qui a des tâches appelées messages qui doivent être traitées.

Note: Android maintient un MessageQueue sur le fil principal.

Looper :

Looper est un ouvrier qui sert une MessageQueue pour le fil courant. Looper effectue des boucles dans la file d'attente des messages et envoie les messages aux gestionnaires correspondants pour les traiter.

N'importe quel fil ne peut avoir qu'un seul Looper unique, cette contrainte est réalisée en utilisant un concept de stockage ThreadLocal.

avantages de Looper et MessageQueue

il y a certains avantages à utiliser Looper et MessageQueue comme décrit ci - dessous -

· avec l'utilisation de L'exécution de MessageQueue est séquentielle donc en cas de threads concurrents, cela évitera les conditions de course.

· Normalement fil ne peut pas être réutilisé une fois son travail terminé. Mais le thread avec Looper est maintenu en vie jusqu'à ce que vous appeliez la méthode quit donc vous n'avez pas besoin de créer une nouvelle instance chaque fois que vous voulez exécuter un travail dans fond.

Gestionnaire:

un gestionnaire permet de communiquer avec le fil UI d'un autre fil d'arrière-plan. Ceci est utile pour android Car android ne permet pas aux autres threads de communiquer directement avec UI thread.

un gestionnaire vous permet d'envoyer et de traiter des messages et des objets exécutables associés à la MessageQueue d'un thread. Chaque instance du gestionnaire est associée à un seul thread et que la file d'attente de messages de thread.

lorsque vous créez un nouveau Gestionnaire, il est lié au thread / message queue du thread qui le crée - à partir de ce point, il délivrera des messages et des exécutables à cette file d'attente de messages et les exécutera lorsqu'ils sortiront de la file d'attente de messages.

il y a deux utilisations principales pour un Handler:

(1) pour programmer les messages et les runnables à exécuter comme un point dans le futur. En d'autres termes effectuer action sur le même fil à l'avenir.

(2) Pour mettre en file d'attente d'une action à effectuer sur un thread différent de celui de votre propre. En d'autres termes, s'enquérir d'une action à exécuter sur un fil différent.

1
répondu neeraj kirola 2018-04-07 10:01:07