Ich bin neu in Android. Ich möchte wissen, was die Looper
Klasse macht und wie man sie benutzt. Ich habe die Dokumentation zur Android Looper-Klasse gelesen, kann sie jedoch nicht vollständig verstehen. Ich habe es an vielen Orten gesehen, kann aber seinen Zweck nicht verstehen. Kann mir jemand helfen, indem er den Zweck von definiert Looper
und wenn möglich auch ein einfaches Beispiel gibt?
android
multithreading
android-looper
Khawar Raza
quelle
quelle
Antworten:
Was ist Looper?
Looper ist eine Klasse, mit der die Nachrichten (Runnables) in einer Warteschlange ausgeführt werden. Normale Threads haben keine solche Warteschlange, z. B. hat ein einfacher Thread keine Warteschlange. Es wird einmal ausgeführt und nach Abschluss der Methodenausführung führt der Thread keine weitere Nachricht aus (ausführbar).
Wo können wir die Looper-Klasse verwenden?
Wenn jemand mehrere Nachrichten (Runnables) ausführen möchte, sollte er die Looper-Klasse verwenden, die für das Erstellen einer Warteschlange im Thread verantwortlich ist. Während wir beispielsweise eine Anwendung schreiben, die Dateien aus dem Internet herunterlädt, können wir die Looper-Klasse verwenden, um herunterzuladende Dateien in die Warteschlange zu stellen.
Wie es funktioniert?
Es gibt eine
prepare()
Methode zur Vorbereitung des Looper. Anschließend können Sie mithilfe derloop()
Methode eine Nachrichtenschleife im aktuellen Thread erstellen. Jetzt ist Ihr Looper bereit, die Anforderungen in der Warteschlange auszuführen, bis Sie die Schleife verlassen.Hier ist der Code, mit dem Sie den Looper vorbereiten können.
quelle
Sie können besser verstehen, was Looper im Kontext des GUI-Frameworks ist. Looper ist dafür gemacht, zwei Dinge zu tun.
1) Looper transformiert einen normalen Thread , der beendet wird, wenn seine run () -Methode zurückgegeben wird, in etwas, das kontinuierlich ausgeführt wird, bis die Android-App ausgeführt wird , die im GUI-Framework benötigt wird (technisch gesehen wird es immer noch beendet, wenn die run () -Methode zurückgegeben wird klären, was ich unten meine).
2) Looper stellt eine Warteschlange bereit, in der zu erledigende Jobs in die Warteschlange gestellt werden, was auch im GUI-Framework erforderlich ist.
Wie Sie vielleicht wissen, erstellt das System beim Start einer Anwendung einen Ausführungsthread für die Anwendung mit dem Namen "main", und Android-Anwendungen werden normalerweise vollständig auf einem einzelnen Thread ausgeführt, standardmäßig dem "main thread". Aber der Haupt-Thread ist kein geheimer, spezieller Thread . Es ist nur ein normaler Thread, der Threads ähnelt, die Sie mit
new Thread()
Code erstellen. Dies bedeutet, dass er beendet wird, wenn die run () -Methode zurückgegeben wird! Denken Sie an das folgende Beispiel.Wenden wir dieses einfache Prinzip nun auf Android-Apps an. Was würde passieren, wenn eine Android-App auf einem normalen Thread ausgeführt wird? Ein Thread namens "main" oder "UI" oder was auch immer startet Ihre Anwendung und zeichnet alle UI. Daher wird den Benutzern der erste Bildschirm angezeigt. So was jetzt? Der Haupt-Thread endet? Nein, das sollte es nicht. Es sollte warten, bis Benutzer etwas tun, oder? Aber wie können wir dieses Verhalten erreichen? Nun, wir können es mit
Object.wait()
oder versuchenThread.sleep()
. Beispielsweise beendet der Hauptthread seinen anfänglichen Job zum Anzeigen des ersten Bildschirms und schläft. Es erwacht, was bedeutet, unterbrochen, wenn ein neuer Job abgerufen wird. So weit so gut, aber in diesem Moment brauchen wir eine warteschlangenartige Datenstruktur, um mehrere Jobs zu halten. Denken Sie an einen Fall, in dem ein Benutzer den Bildschirm seriell berührt und eine Aufgabe länger dauert. Wir brauchen also eine Datenstruktur, um Jobs zu speichern, die First-In-First-Out ausgeführt werden. Sie können sich auch vorstellen, dass die Implementierung eines Threads, der ständig ausgeführt wird und einen Job bei Ankunft verarbeitet, mithilfe von Interrupt nicht einfach ist und zu komplexem und häufig nicht wartbarem Code führt. Wir möchten lieber einen neuen Mechanismus für diesen Zweck schaffen, und darum geht es bei Looper . Das offizielle Dokument der Looper-Klassesagt: "Threads sind standardmäßig keine Nachrichtenschleife zugeordnet", und Looper ist eine Klasse, "die zum Ausführen einer Nachrichtenschleife für einen Thread verwendet wird". Jetzt können Sie verstehen, was es bedeutet.Um die Dinge klarer zu machen, überprüfen wir den Code, in dem der Hauptthread transformiert wird. Alles geschieht in der ActivityThread-Klasse . In seiner main () -Methode finden Sie unten Code, der einen normalen Hauptthread in etwas verwandelt, was wir brauchen.
und
Looper.loop()
Methodenschleife unendlich und eine Nachricht aus der Warteschlange entfernen und einzeln verarbeiten:Im Grunde genommen ist Looper eine Klasse, die entwickelt wurde, um ein Problem zu beheben, das im GUI-Framework auftritt. Diese Art von Bedürfnissen kann aber auch in anderen Situationen auftreten. Tatsächlich ist es ein ziemlich berühmtes Muster für Anwendungen mit mehreren Threads, und Sie können mehr darüber in " Concurrent Programming in Java " von Doug Lea erfahren (insbesondere Kapitel 4.1.4 "Worker Threads" wäre hilfreich). Sie können sich auch vorstellen, dass diese Art von Mechanismus im Android-Framework nicht eindeutig ist, aber alle GUI-Frameworks benötigen möglicherweise etwas Ähnliches. Sie finden fast den gleichen Mechanismus im Java Swing Framework.
quelle
Mit Looper können Aufgaben nacheinander in einem einzelnen Thread ausgeführt werden. Und der Handler definiert die Aufgaben, die ausgeführt werden müssen. Es ist ein typisches Szenario, das ich in diesem Beispiel veranschaulichen möchte:
Jetzt können wir den Handler in einigen anderen Threads (z. B. UI-Thread) verwenden, um die auszuführende Aufgabe auf Looper zu veröffentlichen.
Auf dem UI-Thread haben wir einen impliziten Looper, mit dem wir die Nachrichten auf dem UI-Thread verarbeiten können.
quelle
Android
Looper
ist ein Wrapper anhängenMessageQueue
zuThread
und verwaltet Queue - Verarbeitung. In der Android-Dokumentation sieht es sehr kryptisch aus, und häufigLooper
treten Probleme mit dem Zugriff auf die Benutzeroberfläche auf. Wenn wir die Grundlagen nicht verstehen, wird es sehr schwierig, damit umzugehen.Hier ist ein Artikel, der den
Looper
Lebenszyklus, seine Verwendung und die Verwendung vonLooper
in erklärtHandler
Looper = Thread + MessageQueue
quelle
Definition von Looper & Handler:
Looper ist eine Klasse, die einen Thread in einen Pipeline-Thread und -Handler verwandelt bietet Ihnen einen Mechanismus, mit dem Sie Aufgaben von anderen Threads in den Thread übertragen können.
Einzelheiten:
Ein PipeLine-Thread ist also ein Thread, der über einen Handler mehr Aufgaben von anderen Threads annehmen kann.
Der Looper heißt so, weil er die Schleife implementiert - übernimmt die nächste Aufgabe, führt sie aus, übernimmt dann die nächste und so weiter. Der Handler wird als Handler bezeichnet, da er verwendet wird, um die nächste Aufgabe jedes Mal von einem anderen Thread aus zu bearbeiten oder zu akzeptieren und an Looper (Thread oder PipeLine-Thread) zu übergeben.
Beispiel:
Das perfekte Beispiel für einen Looper and Handler- oder PipeLine-Thread besteht darin, mehr als ein Bild herunterzuladen oder einzeln in einem einzelnen Thread auf einen Server (Http) hochzuladen, anstatt für jeden Netzwerkaufruf im Hintergrund einen neuen Thread zu starten.
Lesen Sie hier mehr über Looper und Handler und die Definition des Pipeline-Threads:
Android Guts: Einführung in Loopers und Handler
quelle
Ein Looper verfügt über einen
synchronized
MessageQueue
, der zum Verarbeiten von Nachrichten verwendet wird, die in die Warteschlange gestellt werden.Es implementiert ein
Thread
bestimmtes Speichermuster.Nur eine
Looper
proThread
. Key - Verfahren umfassenprepare()
,loop()
undquit()
.prepare()
Initialisiert den StromThread
alsLooper
.prepare()
ist einestatic
Methode, die dieThreadLocal
Klasse wie unten gezeigt verwendet.prepare()
muss explizit aufgerufen werden, bevor die Ereignisschleife ausgeführt wird.loop()
Führt die Ereignisschleife aus, die darauf wartet, dass Nachrichten in der Nachrichtenwarteschlange eines bestimmten Threads eintreffen. Sobald die nächste Nachricht empfangen wurde,loop()
sendet die Methode die Nachricht an ihren Zielhandlerquit()
fährt die Ereignisschleife herunter. Die Schleife wird nicht beendet, sondern eine spezielle Nachricht in die Warteschlange gestelltLooper
kann inThread
mehreren Schritten programmiert werdenErweitern
Thread
Aufruf
Looper.prepare()
zum Initialisieren von Thread alsLooper
Erstellen Sie eine oder mehrere
Handler
, um die eingehenden Nachrichten zu verarbeitenLooper.loop()
zur Verarbeitung von Nachrichten, bis die Schleife dazu aufgefordert wirdquit()
.quelle
Die Lebensdauer von Java Thread ist nach Abschluss der
run()
Methode abgelaufen. Der gleiche Thread kann nicht erneut gestartet werden.Looper verwandelt normal
Thread
in eine Nachrichtenschleife. Schlüsselmethoden vonLooper
sind:Dieser Mindorks-Artikel von Janishar erklärt die Kernkonzepte auf nette Weise.
Looper
ist einem Thread zugeordnet. Wenn Sie brauchenLooper
UI-Thread ,Looper.getMainLooper()
wird der zugehörige Thread zurückgegeben.Sie müssen
Looper
mit einem verknüpft sein Handler zugeordnet sein .Looper
,Handler
UndHandlerThread
sind der Weg des Android, die Probleme der asynchronen Programmierung zu lösen.Sobald Sie haben
Handler
, können Sie unten APIs aufrufen.HandlerThread ist eine praktische Klasse zum Starten eines neuen Threads mit einem Looper. Der Looper kann dann zum Erstellen von Handlerklassen verwendet werden
In einigen Szenarien können Sie nicht ausführen
Runnable
Aufgaben auf dem UI-Thread ausführen. zB Netzwerkvorgänge: Senden Sie eine Nachricht an einen Socket, öffnen Sie eine URL und erhalten Sie Inhalte durch LesenInputStream
In diesen Fällen
HandlerThread
ist nützlich. Sie können erhaltenLooper
Objekt ausHandlerThread
und erstellenHandler
aufHandlerThread
statt Haupt - Thread.Der HandlerThread- Code sieht folgendermaßen aus:
Beispielcode finden Sie im folgenden Beitrag:
Android: Toast in einem Thread
quelle
Grundlegendes zu Looper-Threads
Ein Java-Thread eine Ausführungseinheit, die entwickelt wurde, um eine Aufgabe in ihrer run () -Methode auszuführen und danach zu beenden:
Aber in Android gibt es viele Anwendungsfälle, in denen wir einen Thread am Leben erhalten und auf Benutzereingaben / -ereignisse warten müssen, z. UI-Thread aka
Main Thread
.Der Hauptthread in Android ist ein Java-Thread, der beim Start einer App zuerst von JVM gestartet wird und so lange ausgeführt wird, bis der Benutzer ihn schließt oder auf eine nicht behandelte Ausnahme stößt.
Hier ist zu beachten, dass der Hauptthread zwar ein Java-Thread ist, aber weiterhin Benutzerereignisse abhört und 60-fps-Frames auf dem Bildschirm zeichnet und dennoch nicht nach jedem Zyklus stirbt. wie ist es so
Threads ist standardmäßig keine Nachrichtenschleife zugeordnet. Sie können jedoch eine zuweisen, indem Sie Looper.prepare () in der Ausführungsmethode aufrufen und dann Looper.loop () aufrufen.
Wenn Sie genauer wissen möchten, wie Looper die
Message
Objektwarteschlange verwaltet , können Sie sich den Quellcode von Folgendem ansehenLooperclass
:Im Folgenden finden Sie ein Beispiel dafür, wie Sie eine Klasse erstellen
Looper Thread
und mit ihr kommunizierenActivity
könnenLocalBroadcast
Verwendung :
Können wir stattdessen Async-Task oder Intent Services verwenden?
Asynchrone Aufgaben dienen dazu, eine kurze Operation im Hintergrund auszuführen und Fortschritte und Ergebnisse auf dem UI-Thread zu liefern. Async-Aufgaben haben Grenzen, da Sie nicht mehr als 128 Async-Aufgaben erstellen können und
ThreadPoolExecutor
nur bis zu 5 Async-Aufgaben zulassen .IntentServices
sind auch für Hintergrundaufgaben konzipiert, mit denen Sie etwas längerLocalBroadcast
kommunizieren könnenActivity
. Dienste werden jedoch nach der Ausführung der Aufgabe zerstört. Wenn Sie es für eine lange Zeit am Laufen halten wollen, dann müssen Sie wie zum Teufel tunwhile(true){...}
.Andere sinnvolle Anwendungsfälle für Looper Thread:
Wird für die 2-Wege-Socket-Kommunikation verwendet, bei der der Server weiterhin den Client-Socket abhört und die Bestätigung zurückschreibt
Bitmap-Verarbeitung im Hintergrund. Übergeben Sie die Bild-URL an den Looper-Thread. Sie wendet Filtereffekte an, speichert sie an einem temporären Ort und sendet dann den temporären Pfad des Bildes.
quelle
Diese Antwort hat nichts mit der Frage zu tun, aber die Verwendung von Looper und die Art und Weise, wie die Leute den Handler und Looper in ALLEN Antworten hier erstellt haben, sind einfach schlechte Praxis (einige Erklärungen sind jedoch korrekt). Ich muss Folgendes posten:
und für eine vollständige Umsetzung
quelle
Ein besseres Beispiel ist die Behandlung mehrerer Down- oder Upload-Elemente in einem Service .
Handler
undAsnycTask
werden häufig verwendet, um Ereignisse / Nachrichten zwischen der Benutzeroberfläche (Thread) und einem Arbeitsthread zu verbreiten oder Aktionen zu verzögern. Sie sind also eher mit der Benutzeroberfläche verbunden.A
Looper
verarbeitet Aufgaben ( Runnables, Futures ) in einer Thread-bezogenen Warteschlange im Hintergrund - auch ohne Benutzerinteraktion oder angezeigte Benutzeroberfläche (App lädt während eines Anrufs eine Datei im Hintergrund herunter).quelle
VON DOKUMENTEN
Looper
Looper
Klasse zum Ausführen einer Nachrichtenschleife für athread
. Threads sind standardmäßig keine Nachrichtenschleife zugeordnet. Um einen zu erstellen, rufen Sieprepare()
den Thread auf, der die Schleife ausführen soll, und lassen Sie ihn dannloop()
Nachrichten verarbeiten, bis die Schleife gestoppt ist.Looper
ist eine Nachrichtenbehandlungsschleife:MessageQueue
, die eine Listennachricht enthält. Ein wichtiges Merkmal von Looper ist, dass es dem Thread zugeordnet ist, in dem der Looper erstellt wird.Looper
heißt so, weil es die Schleife implementiert - nimmt die nächste Aufgabe, führt sie aus, nimmt dann die nächste und so weiter. DasHandler
wird als Handler bezeichnet, weil jemand keinen besseren Namen erfinden könnteLooper
ist eine Java-Klasse in der Android-Benutzeroberfläche, die zusammen mit der Handler-Klasse UI-Ereignisse wie Schaltflächenklicks, Neuzeichnungen des Bildschirms und Ausrichtungswechsel verarbeitet.Ein Thread erhält ein
Looper
undMessageQueue
durch AufrufenLooper.prepare()
nach seiner Ausführung.Looper.prepare()
Identifiziert den aufrufenden Thread, erstellt einen Looper und einMessageQueue
Objekt und ordnet den Thread zuBEISPIELCODE
Weitere Informationen finden Sie unten im Beitrag
quelle