Quand j'ai besoin de quelque chose à exécuter de manière asynchrone , comme un tâche longue ou une logique qui utilise le réseau, ou quoi que raison, à partir de nouvelle discussion et en cours d'exécution cela fonctionne très bien. Créer un Handler et l'exécuter fonctionne également. Quelle est la différence? Quand devrais-je utiliser chacun? Quels sont les avantages/raisons d'utiliser un Handler
et non un Thread
?
PS - Pour cette question, ignorons AsyncTask
. - Handler().postDelayed
le cas d'utilisation est clair pour moi, supposons que j'ai besoin que la tâche commence immédiatement.
Si tout ce que vous faites est "lourd", vous devriez le faire dans un fil. Si vous ne le démarrez pas explicitement dans son propre thread, il s'exécutera sur le thread principal (interface utilisateur) qui peut être perçu comme une interface instable ou lente à répondre par vos utilisateurs.
Il est intéressant de noter que lorsque vous utilisez un fil, il est souvent utile d’utiliser également un gestionnaire comme moyen de communication entre le fil de travail que vous démarrez et le fil principal.
Une interaction typique Thread/Handler pourrait ressembler à ceci:
Handler h = new Handler(){
@Override
public void handleMessage(Message msg){
if(msg.what == 0){
updateUI();
}else{
showErrorDialog();
}
}
};
Thread t = new Thread() {
@Override
public void run(){
doSomeWork();
if(succeed){
//we can't update the UI from here so we'll signal our handler and it will do it for us.
h.sendEmptyMessage(0);
}else{
h.sendEmptyMessage(1);
}
}
};
En règle générale, toutefois, vous devez utiliser un fil de discussion chaque fois que vous effectuez un travail qui peut être long ou très intensif (c’est-à-dire tout réseau, IO de fichier, arithmatique lourd, etc.).
Handler et Thread sont vraiment 2 choses différentes.
Un thread doit être créé pour exécuter des travaux de longue durée.
Un gestionnaire est un objet très pratique pour communiquer entre 2 threads (par exemple: un thread d'arrière-plan doit mettre à jour l'interface utilisateur. Vous pouvez utiliser un gestionnaire pour publier des fichiers Runnable de votre thread d'arrière-plan dans le thread d'interface utilisateur).
Donc, vous n'avez pas le choix entre Handler ou Thread. Utilisez un fil pour faire des travaux lourds! (vous pouvez utiliser un gestionnaire si votre thread d'arrière-plan déclenche l'exécution d'un travail dans un autre thread - la plupart du temps le thread d'interface utilisateur)
Handler
et Thread
sont deux choses différentes, mais elles ne se contredisent pas. Vous pouvez avoir un Handler
et un Thread
en même temps et, en réalité, chaque Handler
doit être exécuté dans un Thread
.
Pour plus de détails, vous voudrez peut-être consultez cet article .
Un Handler
s'exécute sur le même Thread
, un Thread
s'exécute sur un autre thread.
tilisez un gestionnaire si vous devez exécuter quelque chose sur le même thread, généralement un élément graphique ou quelque chose comme ça.
tilisez un thread si vous voulez garder le thread principal libre de faire d'autres choses. Utilisez ceci pour tout ce qui prend beaucoup de temps.
Les gestionnaires sont le meilleur moyen de communication entre l’arrière-plan et le fil de l’interface utilisateur. Généralement, les gestionnaires sont associés à la file de messages d'un thread et sont utilisés pour envoyer des messages et peuvent être exécutés dans le message.
USE:
Thread: Pour effectuer des tâches dans un thread saperate (Background) par rapport à un thread UI. (aide à débloquer le thread d'interface utilisateur)
Gestionnaire Utilisé pour communiquer entre le thread d'interface utilisateur et le fil d'arrière-plan.
Regardez ceci article
Si vous devez mettre à jour l'interface utilisateur à partir d'un nouveau thread, vous devez vous synchroniser avec le thread d'interface utilisateur.
Vous pouvez utiliser la classe Android.os.Handler ou la classe AsyncTasks pour cela.
La classe Handler peut mettre à jour l'interface utilisateur. Un gestionnaire fournit des méthodes pour recevoir des instances de la classe Message ou Runnable.
Votre thread peut poster des messages via la méthode sendMessage (Message msg) ou via la méthode sendEmptyMessage ().
... plus d'infos ici sur les threads, etc. (inclut des références pour les différents mécanismes de threading et de synchronisation et quand utiliser quoi)
Quels sont les avantages/raisons d'utiliser un gestionnaire et non un fil?
Un gestionnaire vous permet d'envoyer et de traiter les objets Message et Runnable
associés au MessageQueue
d'un thread. Chaque instance Handler
est associée à un seul thread et à la file de messages de ce thread.
Lorsque vous créez un nouveau Handler
, il est lié au thread/à la file de messages du thread qui le crée - à partir de ce moment, il livrera les messages et les variables exécutables à cette file de messages et les exécutera au fur et à mesure hors de la file d'attente des messages.
Il y a deux utilisations principales pour un gestionnaire:
Si vous utilisez Java thread, vous devez gérer vous-même quelque chose - synchronisation avec le thread principal, annulation d'un thread, etc.
Ce thread unique ne crée pas de pool de threads sauf si vous utilisez ThreadPoolExecutor
ou ExecutorService
API.
(Tiré de cette requête de vos commentaires sur la réponse Blackbelt)
Pourquoi ne pas utiliser un exécuteur? et même si je voulais utiliser un gestionnaire pour le faire, comment?
Référence: article sur les performances de thread
Certains types de travail peuvent être réduits à des tâches hautement parallèles et distribuées. Avec le volume considérable de paquets de travail que cela crée, AsyncTask
et HandlerThread
ne sont pas des classes appropriées. La nature mono-threadée de AsyncTask
transformerait tout le travail en pool threadé en un système linéaire. Par contre, pour utiliser la classe HandlerThread
, le programmeur devrait gérer manuellement l’équilibrage de la charge entre un groupe de threads.
ThreadPoolExecutor est une classe d'assistance facilitant ce processus. Cette classe gère la création d'un groupe de threads, définit leurs priorités et gère la répartition du travail entre ces threads. Lorsque la charge de travail augmente ou diminue, la classe augmente ou détruit davantage de threads pour s'adapter à la charge de travail.
BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
ThreadPoolExecutor executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(), // Initial pool size
Runtime.getRuntime().availableProcessors(), // Max pool size
1, // KEEP_ALIVE_TIME
TimeUnit.SECONDS, // KEEP_ALIVE_TIME_UNIT
workQueue);
Vous pouvez vous référer à cet article du guide du développeur sur create-threadpool pour plus de détails.
Jetez un coup d'œil à cet article pour savoir comment utiliser Handler
pour exécuter plusieurs instances de Runnable. Dans ce cas, toutes les tâches Runnable
seront exécutées dans un seul thread.
Handler
peut être utilisé avec Thread
afin de créer un mécanisme en file d'attente. Vous pouvez utiliser la handler
pour publier quelque chose sur la Thread
Looper