web-dev-qa-db-fra.com

Android: Quand dois-je utiliser un gestionnaire () et quand dois-je utiliser un thread?

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.

126
JRun

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.).

163
FoamyGuy

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)

61
ben75

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 .

enter image description here

28
pierrotlefou

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.

18
PearsonArtPhoto

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

13

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)

4
Beachwalker

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:

  1. Pour programmer des messages et des runnables à exécuter à un moment donné
  2. Pour mettre en file d'attente une action à exécuter sur un autre thread que le vôtre.

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.

Android: Toast dans un fil

2
Ravindra babu

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 ThreadLooper

1
Blackbelt