398 Stimmen

Handler vs. AsyncTask vs. Thread

Ich war etwas verwirrt über die Unterschiede zwischen Handlers , AsyncTask y Threads in Android. Ich habe eine ganze Reihe von Blogs und Fragen hier in StackOverflow gelesen.

Handler sind Hintergrund-Threads, die Ihnen die Kommunikation mit der Benutzeroberfläche ermöglichen. Die Aktualisierung eines Fortschrittsbalkens zum Beispiel sollte über Handler . Die Verwendung von Handlern hat den Vorteil, dass sie MessagingQueues Wenn Sie also Nachrichten planen, mehrere Elemente der Benutzeroberfläche aktualisieren oder sich wiederholende Aufgaben durchführen möchten, können Sie dies tun.

AsyncTask ähneln sich in der Tat, denn sie nutzen die Handler , läuft aber nicht im UI-Thread und eignet sich daher gut zum Abrufen von Daten, z. B. zum Abrufen von Webdiensten. Später können Sie mit der Benutzeroberfläche interagieren.

Thread kann jedoch nicht mit der Benutzeroberfläche interagieren, bietet "einfacheres" Threading und man vermisst alle Abstraktionen von AsyncTask .

Ich möchte jedoch eine Socket-Verbindung im Dienst laufen lassen. Sollte dies in einem Handler oder einem Thread oder sogar einem AsyncTask ? UI-Interaktion ist überhaupt nicht notwendig. Macht es einen Unterschied in Bezug auf die Leistung, welche ich verwende?

Inzwischen ist die Dokumentation wurde erheblich verbessert.

359voto

hqt Punkte 28296

Wenn wir uns den Quellcode ansehen, werden wir sehen AsyncTask y Handler ist rein in Java geschrieben. (Es gibt allerdings einige Ausnahmen, aber das ist nicht wichtig)

Es gibt also keine Magie in AsyncTask o Handler . Diese Klassen machen uns als Entwickler das Leben leichter.

Zum Beispiel: Wenn Programm A die Methode A() aufruft, könnte die Methode A() in einem anderen Thread mit Programm A ausgeführt werden. Dies lässt sich mit dem folgenden Code leicht überprüfen:

Thread t = Thread.currentThread();    
int id = t.getId();

Warum sollten wir für manche Aufgaben einen neuen Thread verwenden? Sie können danach googeln. Viele, viele Gründe, z.B.: schweres Heben, langwierige Arbeiten.

Was sind also die Unterschiede zwischen Thread , AsyncTask y Handler ?

AsyncTask y Handler sind in Java geschrieben (intern verwenden sie eine Thread ), also alles, was wir mit Handler o AsyncTask können wir mit einer Thread zu.

Was kann Handler y AsyncTask wirklich helfen?

Der offensichtlichste Grund ist die Kommunikation zwischen dem Aufrufer-Thread und dem Worker-Thread. ( Anrufer-Thread : Ein Thread, der die Arbeitsthread um einige Aufgaben zu erfüllen. Der aufrufende Thread muss nicht unbedingt der UI-Thread sein). Natürlich können wir zwischen zwei Threads auch auf andere Weise kommunizieren, aber es gibt viele Nachteile (und Gefahren) aufgrund der Thread-Sicherheit.

Deshalb sollten wir die Handler y AsyncTask . Diese Klassen nehmen uns die meiste Arbeit ab, wir müssen nur wissen, welche Methoden wir außer Kraft setzen wollen.

Der Unterschied zwischen Handler y AsyncTask ist: Verwenden Sie AsyncTask wenn Anrufer-Thread es un UI-Thread . So steht es im Android-Dokument:

AsyncTask ermöglicht die korrekte und einfache Verwendung des UI-Threads. Diese Klasse ermöglicht die Durchführung von Hintergrundoperationen und die Veröffentlichung von Ergebnissen auf dem UI Thread zu veröffentlichen, ohne Threads und/oder Handler manipulieren zu müssen

Ich möchte zwei Punkte hervorheben:

1) Einfache Verwendung des UI-Threads (also Verwendung, wenn der Aufrufer-Thread der UI-Thread ist).

2) Keine Manipulation der Handler erforderlich. (bedeutet: Sie können Handler anstelle von AsyncTask verwenden, aber AsyncTask ist eine einfachere Option).

Es gibt viele Dinge in diesem Beitrag, die ich noch nicht gesagt habe, zum Beispiel: was ist UI Thread, oder warum es einfacher ist. Sie müssen wissen, einige Methoden hinter jeder Klasse und verwenden Sie es, Sie werden vollständig den Grund, warum zu verstehen.

@: Wenn Sie das Android-Dokument lesen, werden Sie sehen:

Handler ermöglicht das Senden und Verarbeiten von Nachrichten und Runnable-Objekten die mit der MessageQueue eines Threads verbunden sind

Diese Beschreibung mag auf den ersten Blick seltsam erscheinen. Wir müssen nur verstehen, dass jeder Thread eine Nachrichtenwarteschlange hat (wie eine Aufgabenliste), und der Thread nimmt jede Nachricht und erledigt sie, bis die Nachrichtenwarteschlange leer ist (so wie wir unsere Arbeit beenden und ins Bett gehen). Also, wenn Handler kommuniziert, gibt er nur eine Nachricht an den aufrufenden Thread weiter und wartet auf die Verarbeitung.

Kompliziert? Denken Sie einfach daran, dass Handler sicher mit dem aufrufenden Thread kommunizieren kann.

61voto

Daniel F Punkte 12908

Das Tutorial zu Android-Hintergrundverarbeitung mit Handlern, AsyncTask und Loadern auf der Vogella-Website formuliert:

En Handler Klasse kann verwendet werden, um sich bei einem Thread zu registrieren und bietet einen einfachen Kanal, um Daten an diesen Thread zu senden.

En AsyncTask Klasse kapselt die Erstellung eines Hintergrundprozesses und die Synchronisation mit dem Hauptthread. Sie unterstützt auch die Meldung des Fortschritts der laufenden Aufgaben.

Und ein Thread ist im Grunde das Kernelement des Multithreading, das ein Entwickler mit folgendem Nachteil nutzen kann:

Wenn Sie Java-Threads verwenden, müssen Sie die folgenden Anforderungen erfüllen in Ihrem eigenen Code behandeln:

  • Synchronisierung mit dem Hauptthread, wenn Sie Ergebnisse an die Benutzeroberfläche zurückgeben
  • Kein Standard für das Abbrechen des Threads
  • Kein Standard-Thread-Pooling
  • Kein Standard für die Behandlung von Konfigurationsänderungen in Android

Und was die AsyncTask als die Referenz für Android-Entwickler drückt es aus:

AsyncTask ermöglicht die korrekte und einfache Verwendung des UI-Threads. Diese Klasse ermöglicht die Durchführung von Hintergrundoperationen und die Veröffentlichung von Ergebnissen auf dem UI Thread durchzuführen und Ergebnisse zu veröffentlichen, ohne Threads und/oder Handler manipulieren zu müssen.

AsyncTask ist als Hilfsklasse für Thread y Handler und stellt keinen generischen Rahmen für das Threading dar. AsyncTasks sollte idealerweise für kurze Operationen verwendet werden (höchstens ein paar Sekunden höchstens.) Wenn Sie Threads über längere Zeiträume laufen lassen müssen, ist es sehr empfehlenswert, die verschiedenen APIs zu verwenden, die durch das java.util.concurrent-Paket bereitgestellt werden, wie Executor, ThreadPoolExecutor und FutureTask.

Update Mai 2015: Ich habe eine ausgezeichnete Vortragsreihe über dieses Thema.

Dies ist die Google-Suche: Douglas Schmidt Vorlesung Android Gleichzeitigkeit und Synchronisation

Dies ist das Video der erste Vorlesung auf YouTube

All dies ist Teil der CS 282 (2013): Systemprogrammierung für Android von der Vanderbilt Universität . Hier ist die YouTube-Wiedergabeliste

Douglas Schmidt scheint ein ausgezeichneter Dozent zu sein

Das ist wichtig: Wenn Sie an einem Punkt angelangt sind, an dem Sie die Verwendung von AsyncTask um Ihre Probleme mit dem Threading zu lösen, sollten Sie zunächst auschecken ReactiveX/RxAndroid für ein möglicherweise besser geeignetes Programmiermuster. Eine sehr gute Quelle, um sich einen Überblick zu verschaffen, ist RxJava 2 für Android am Beispiel lernen .

22voto

Eugene S Punkte 3052

Eine AsyncTask wird verwendet, um einige Hintergrundberechnungen durchzuführen und das Ergebnis im UI-Thread zu veröffentlichen (mit optionalen Fortschrittsaktualisierungen). Da Sie sich nicht mit der Benutzeroberfläche befassen, ist ein Handler o Thread scheint angemessener zu sein.

Sie können einen Hintergrund spawnen Thread und leiten Sie Nachrichten an Ihren Hauptthread zurück, indem Sie die Handler 's post Methode.

8voto

Ravindra babu Punkte 45577

Thread :

Sie können die neue Thread für langlaufende Hintergrundaufgaben ohne Beeinträchtigung des UI-Threads. Vom Java-Thread aus können Sie den UI-Thread nicht aktualisieren.

Da normale Thema für die Android-Architektur nicht sehr nützlich ist, wurden Hilfsklassen für das Threading eingeführt.

Antworten auf Ihre Fragen finden Sie unter Leistung beim Einfädeln Dokumentationsseite.

Handler :

A Handler ermöglicht Ihnen das Senden und Verarbeiten von Nachrichten und Runnable Objekte, die mit dem Thread MessageQueue . Jede Handler Instanz ist mit einem einzelnen Thread und der Nachrichtenwarteschlange dieses Threads verbunden.

Es gibt zwei Hauptverwendungszwecke für eine Handler :

  1. Zur Planung von Nachrichten und Runnables, die zu einem bestimmten Zeitpunkt in der Zukunft ausgeführt werden sollen;

  2. Um eine Aktion in die Warteschlange zu stellen, die in einem anderen Thread als dem eigenen ausgeführt werden soll.

AsyncTask :

AsyncTask ermöglicht die korrekte und einfache Verwendung des UI-Threads. Mit dieser Klasse können Sie Hintergrundoperationen durchführen und Ergebnisse auf dem UI-Thread veröffentlichen, ohne Threads und/oder Handler manipulieren zu müssen.

Nachteilig:

  1. Standardmäßig verschiebt eine App alle AsyncTask Objekte, die es erstellt, in einen einzigen Thread. Daher werden sie seriell ausgeführt, und - wie beim Hauptthread - kann ein besonders langes Arbeitspaket die Warteschlange blockieren. Aus diesem Grund sollten Sie AsyncTask verwenden, um Workitems zu behandeln, die kürzer als 5ms Dauer .

  2. AsyncTask Objekte sind auch die häufigsten Verursacher von Problemen mit impliziten Verweisen. AsyncTask Objekte bergen auch Risiken im Zusammenhang mit ausdrücklichen Verweisen.

HandlerThread :

Möglicherweise benötigen Sie einen traditionelleren Ansatz für die Ausführung eines Arbeitsblocks in einem lang laufenden Thread ( im Gegensatz zu AsyncTask, das für 5ms-Workloads verwendet werden sollte ) und eine gewisse Fähigkeit, diesen Arbeitsablauf manuell zu verwalten. Ein Handler-Thread ist im Grunde ein lang laufender Thread, der Arbeit aus einer Warteschlange holt und sie bearbeitet.

ThreadPoolExecutor :

Diese Klasse verwaltet die Erstellung einer Gruppe von Threads, legt ihre Prioritäten fest und verwaltet, wie die Arbeit auf diese Threads verteilt wird. Wenn die Arbeitslast steigt oder sinkt, erzeugt oder zerstört die Klasse weitere Threads, um sich der Arbeitslast anzupassen.

Wenn die Arbeitsbelastung höher ist und einzelne HandlerThread nicht ausreicht, können Sie sich für ThreadPoolExecutor

Ich möchte jedoch eine Socket-Verbindung im Dienst laufen lassen. Sollte dies in einem Handler oder einem Thread, oder sogar eine AsyncTask ausgeführt werden? Eine Interaktion mit der Benutzeroberfläche ist überhaupt nicht erforderlich. Macht es einen Unterschied in Bezug auf die Leistung, die ich verwenden?

Da eine Interaktion mit der Benutzeroberfläche nicht erforderlich ist, können Sie sich nicht für AsyncTask . Normale Fäden sind nicht sehr nützlich und daher HandlerThread ist die beste Option. Da Sie die Socket-Verbindung aufrechterhalten müssen, ist ein Handler auf dem Haupt-Thread überhaupt nicht sinnvoll. Erstellen Sie einen HandlerThread und erhalten eine Handler aus dem Looper von HandlerThread .

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

Wenn Sie zurück zum UI-Thread kommunizieren möchten, können Sie einen weiteren Handler verwenden, um die Antwort zu verarbeiten.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

in Ihrem Runnable können Sie hinzufügen

responseHandler.sendMessage(msg);

Weitere Einzelheiten zur Umsetzung finden Sie hier:

Android: Toast in einem Thread

5voto

Brian Punkte 7797

Meiner Meinung nach sind Threads nicht die effizienteste Art, Socket-Verbindungen herzustellen, aber sie bieten die meisten Funktionen in Bezug auf die Ausführung von Threads. Ich sage das, weil ich die Erfahrung gemacht habe, dass Geräte, die über einen längeren Zeitraum Threads ausführen, sehr heiß und ressourcenintensiv werden. Selbst eine einfache while(true) erhitzt ein Telefon in Minutenschnelle. Wenn Sie sagen, dass UI-Interaktion nicht wichtig ist, vielleicht ein AsyncTask ist gut, denn sie sind für langfristige Prozesse ausgelegt. Das ist nur meine Meinung dazu.

UPDATE

Bitte beachten Sie meine obige Antwort nicht! Ich habe diese Frage bereits 2011 beantwortet, als ich noch weit weniger Erfahrung mit Android hatte als heute. Meine Antwort oben ist irreführend und wird als falsch angesehen. Ich lasse sie dort, weil viele Leute sie unten kommentiert haben, um mich zu korrigieren, und ich habe meine Lektion gelernt.

Es gibt weitaus bessere andere Antworten in diesem Thread, aber ich werde zumindest mir eine angemessenere Antwort geben. Es ist nichts falsch mit der Verwendung eines regulären Java Thread Allerdings sollte man bei der Implementierung sehr vorsichtig sein, denn wenn man es falsch macht, kann es sehr prozessorintensiv sein (das auffälligste Symptom ist die Erwärmung des Geräts). AsyncTask s sind ziemlich ideal für die meisten Aufgaben, die im Hintergrund laufen sollen (gängige Beispiele sind Festplatten-E/A, Netzwerkaufrufe und Datenbankaufrufe). Allerdings, AsyncTask s sollten nicht für besonders lange Prozesse verwendet werden, die fortgesetzt werden müssen, nachdem der Benutzer Ihre Anwendung geschlossen oder sein Gerät in den Standby-Modus versetzt hat. Ich würde sagen, dass in den meisten Fällen alles, was nicht in den UI-Thread gehört, in einem anderen Thread erledigt werden kann. AsyncTask .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X