Quel est le but de Looper et comment l'utiliser?
Je suis nouveau sur Android. Je veux savoir ce que fait la classe Looper
et aussi comment l'utiliser. J'ai lu L'Android Looper class documentation mais je ne suis pas en mesure de le comprendre complètement.
Je l'ai vu dans beaucoup d'endroits, mais incapable de comprendre son but. Est-ce que quelqu'un peut m'aider en définissant le but de Looper
et aussi en donnant un exemple simple si possible?
9 réponses
Qu'est-ce que Looper?
Looper est une classe qui est utilisée pour exécuter les Messages(Runnables) dans une file d'attente. Les threads normaux n'ont pas de file d'attente, par exemple le thread simple n'a pas de file d'attente. Il exécute une fois l'exécution de la méthode terminée, le thread n'exécutera pas un autre Message(exécutable).
où peut-on utiliser la classe Looper?
Si quelqu'un veut exécuter plusieurs messages (Runnables) puis il doit utiliser la classe Looper qui est responsable de créer une file d'attente dans le thread. Par exemple, en écrivant une application qui télécharge des fichiers à partir d'internet, nous pouvons utiliser Looper class pour mettre des fichiers à télécharger dans la file d'attente.
comment ça marche?
il y a prepare()
méthode pour préparer le Looper. Ensuite, vous pouvez utiliser la méthode loop()
pour créer une boucle de message dans le thread courant et maintenant votre Looper est prêt à exécuter les requêtes dans la file d'attente jusqu'à ce que vous quittiez la boucle.
Voici le code par lequel vous pouvez préparer le Looper.
class LooperThread extends Thread {
public Handler mHandler;
@Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
vous pouvez mieux comprendre ce Qu'est Looper dans le contexte de GUI framework. Looper est fait pour faire 2 choses.
1) Looper transforme un thread normal , qui se termine lorsque sa méthode run() retourne, en quelque chose continue jusqu'à ce que Android app tourne , ce 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 en 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 fil d'exécution pour l'application, appelé" main", et les applications Android tournent normalement entièrement sur un seul fil par défaut le"fil principal". Mais fil principal n'est pas quelque secret, fil spécial . C'est juste un fil normal similaire aux threads que vous créez 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. Que se passerait-il si une application Android fonctionnait sur le fil normal? Un thread appelé " main "ou" UI " ou n'importe quoi qui commence votre application, et dessine toute L'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. jusqu'à ce 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 file d'attente, comme structure de données pour contenir 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. Donc, nous avons besoin de données structure permettant d'effectuer les travaux de manière "premier arrivé, 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 de boucle de message associé avec eux", et Looper est une classe "utilisé pour exécuter une boucle de message pour un fil". Maintenant tu peux comprendre ce que ça veut dire.
pour rendre les choses plus claires, vérifions le code où le thread principal est transformé. Tout se passe dans Classe ActivityThread . Dans sa méthode main (), vous pouvez trouver ci-dessous le code, qui transforme un thread principal normal en quelque chose dont nous avons besoin.
public final class ActivityThread {
...
public static void main(String[] args) {
...
Looper.prepareMainLooper();
Looper.loop();
...
}
}
Boucle de la méthode et Looper.loop()
infiniment et la file d'attente d'un message et d'un processus à un moment:
public static void loop() {
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg);
...
}
}
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 aussi se produire dans d'autres situations. En fait, il est un modèle assez célèbre pour l'application de threads multiples, et vous pouvez en apprendre plus à ce sujet dans " programmation simultanée en Java " par Doug Lea(en particulier, chapitre 4.1.4 "worker Threads" serait utile). En outre, vous pouvez imaginer ce genre de mécanisme n'est pas unique dans le cadre Android, mais tout cadre GUI peut avoir besoin quelque peu similaire à cela. Vous pouvez trouver presque le même mécanisme dans Java Swing framework.
Looper permet d'exécuter les tâches de façon séquentielle sur un seul thread. Et handler définit les tâches que nous devons exécuter. C'est un scénario typique que j'essaie d'illustrer dans cet exemple:
class SampleLooper extends Thread {
@Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
// now, the handler will automatically bind to the
// Looper that is attached to the current thread
// You don't need to specify the Looper explicitly
handler = new Handler();
// After the following line the thread will start
// running the message loop and will not normally
// exit the loop unless a problem happens or you
// quit() the looper (see below)
Looper.loop();
} catch (Throwable t) {
Log.e(TAG, "halted due to an error", t);
}
}
}
maintenant nous pouvons utiliser le handler dans d'autres threads(disons ui thread) pour poster la tâche sur Looper pour exécuter.
handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
}
});
sur UI thread nous avons un Looper implicite qui nous permet de traiter les messages sur ui thread.
Android Looper
est un wrapper pour attacher MessageQueue
à Thread
et il gère le traitement des files d'attente. Il semble très cryptique dans la documentation Android et de nombreuses fois, nous pouvons faire face à Looper
problèmes d'accès à L'interface utilisateur. Si nous ne comprenons pas les bases, il devient très difficile à manipuler.
Voici une article qui explique Looper
cycle de vie, comment l'utiliser et l'utilisation de Looper
dans Handler
Looper = Thread + MessageQueue
Looper
est une classe qui transforme un filetage en Filetage de Pipeline et Handler
vous donne un mécanisme pour y pousser des tâches à partir de n'importe quel autre filetage.
donc un PipeLine Thread
est un thread qui peut accepter plus de tâches à partir d'autres threads à travers un Handler
.
le Looper est nommé ainsi parce qu'il implémente la boucle – prend la prochaine tâche, l'exécute, puis prend la suivante et ainsi de suite. Le Gestionnaire est appelé un gestionnaire, car il est utilisé pour manipuler ou accepter la tâche suivante à chaque fois à partir de n'importe quel autre fil et passer à Looper (fil ou fil de PipeLine).
L'exemple parfait d'un Looper et D'un Handler ou D'un PipeLine Thread est de télécharger plus d'une image ou de les télécharger sur un serveur (Http) un par un dans un seul thread au lieu de lancer un nouveau Thread pour chaque appel réseau en arrière-plan.
pour en savoir plus sur Looper et Handler et la définition de Pipeline Thread:
Un Looper a une synchronized
MessageQueue
qui est utilisé pour traiter les Messages placés dans la file d'attente.
Il met en œuvre un Thread
Spécifique de la structure de Stockage.
un seul Looper
par Thread
. Les méthodes clés sont prepare()
, loop()
et quit()
.
prepare()
initialise l'actuel Thread
comme un Looper
. prepare()
est static
méthode qui utilise la classe ThreadLocal
comme indiqué ci-dessous.
public static void prepare(){
...
sThreadLocal.set
(new Looper());
}
-
prepare()
doit être explicitement appelé avant d'exécuter la boucle d'événement. -
loop()
exécute la boucle d'événement qui attend les Messages pour arriver sur la messagequeue d'un Thread spécifique. Une fois le Message suivant reçu,la méthodeloop()
envoie le Message à son gestionnaire cible -
quit()
coupe la boucle de l'événement. Il ne termine pas la boucle, mais il demande un message spécial
Looper
peut être programmé dans un Thread
via plusieurs étapes
-
étendre
Thread
-
appel
Looper.prepare()
pour initialiser le fil comme unLooper
-
créer un ou plusieurs
Handler
(s) pour traiter les messages - Appel
Looper.loop()
pour traiter les messages jusqu'à ce que la boucle est ditquit()
.
durée de Vie de java Thread est de plus après la fin de run()
la méthode. Le même fil ne peut pas recommencer.
Looper transforme la normale Thread
en boucle de message. Les principales méthodes de Looper
sont:
void prepare ()
initialise le fil courant comme un looper. Cela vous donne une chance de créer des gestionnaires qui se réfèrent alors à ce looper, avant en fait le démarrage de la boucle. Assurez-vous d'appeler loop() après avoir appelé cette méthode, et terminez en appelant quit().
void loop ()
lancez la file d'attente de messages dans ce thread. N'oubliez pas d'appeler quit() pour mettre fin à la boucle.
void quit()
quitte le looper.
provoque la fin de la méthode loop() sans traiter d'autres messages dans la file d'attente.
Ce mindorks l'article par Janishar explique les principaux concepts de belle manière.
Looper
est associé à un fil. Si vous avez besoin de Looper
sur le fil UI, Looper.getMainLooper()
retournera le fil associé.
Vous avez besoin de Looper
être associé à un Gestionnaire .
Looper
, Handler
, et HandlerThread
sont la façon D'Android de résoudre les problèmes de programmation asynchrone.
une fois que vous avez Handler
, vous pouvez appeler ci-dessous APIs.
post (Runnable r)
fait en sorte que le R exécutable soit ajouté à la file d'attente des messages. L'exécutable sera exécuté sur le fil auquel ce gestionnaire est attaché.
boolean sendMessage (Message msg)
pousse un message à la fin de la file d'attente après tous les messages en attente avant l'heure actuelle. Il sera reçu en handleMessage (Message), dans le thread attaché à ce handler.
HandlerThread est une classe pratique pour démarrer un nouveau fil qui a un looper. Le looper peut alors être utilisé pour créer des classes de handler
dans certains scénarios, vous ne pouvez pas exécuter Runnable
tâches sur L'UI Fil.
par exemple, opérations réseau : envoyer un message sur une socket, ouvrir une URL et obtenir du contenu en lisant InputStream
dans ces cas, HandlerThread
est utile. Vous pouvez obtenir l'objet Looper
de HandlerThread
et créer un Handler
sur HandlerThread
au lieu du fil principal.
le HandlerThread code sera comme ceci:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
se référer à l'exemple de code de poste ci-dessous:
cette réponse n'a rien à voir avec la question, mais l'utilisation de looper et la façon dont les gens ont créé le handler et looper dans toutes les réponses ici sont une mauvaise pratique (quelques explications sont correctes cependant), je dois poster ceci:
HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);
et pour un mise en œuvre complète
, qui traite plusieurs éléments vers le bas ou vers le haut dans un Service en est un meilleur exemple.
Handler
et AsnycTask
sont souvent utilisés pour propager des Evénements/Messages entre le de l'INTERFACE utilisateur (thread) et un thread de travail ou de retarder les actions. Elles sont donc davantage liées à L'assurance-chômage.
Un Looper
poignées de tâches ( Runnables, les contrats à Terme ) dans une fil d'attente l'arrière-plan-même sans aucune interaction utilisateur ou une interface utilisateur affichée (l'application télécharge un fichier en arrière-plan pendant un appel).