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.
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();
}
}
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.
public final class ActivityThread {
...
public static void main(String[] args) {
...
Looper.prepareMainLooper();
Looper.loop();
...
}
}
und Looper.loop()
Methodenschleife unendlich und eine Nachricht aus der Warteschlange entfernen und einzeln verarbeiten:
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);
...
}
}
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.