Android Core verstehen: Looper, Handler und HandlerThread

 Android Core verstehen: Looper, Handler und HandlerThread

Dieser Artikel behandelt Android Looper, Handler und HandlerThread. Diese gehören zu den Bausteinen von Android OS.

Nach meiner eigenen Erfahrung habe ich sie bis vor kurzem in einem sehr begrenzten Kontext verwendet. Mein Anwendungsfall bestand darin, Aufgaben an den Haupt- / ui-Thread zu senden, hauptsächlich um die Benutzeroberfläche von einem anderen Thread aus zu aktualisieren. Die anderen Aspekte der Multithread-Operation wurden auf alternative Weise wie ThreadPoolExecutor , IntentService und AsyncTask .

MultiThreading und Task Running sind alte Themen. Java selbst hat Java.util.concurrent Package und Fork / Join Framework, um es zu erleichtern. Mehrere Bibliotheken wurden geschrieben, um asynchrone Vorgänge zu optimieren. RxJava ist heute die beliebteste Bibliothek zum reaktiven Programmieren und Entwerfen einer asynchronen Anwendung.

Also, warum schreibe ich über die alte Schule?

Looper, Handler, und HandlerThread sind der Android-Weg, um die Probleme der asynchronen Programmierung zu lösen. Sie sind keine alte Schule, sondern eine ordentliche Struktur, auf der ein komplexes Android-Framework aufbaut.

Für neue Entwickler wird dringend empfohlen, die Prinzipien dahinter zu verstehen, und erfahrene sollten dieses Thema erneut besuchen, um sich an die kleinen Details zu erinnern.

Ich habe auch ein Video-Tutorial zu diesem Thema erstellt, und ich empfehle dringend, es zu sehen. Klicken Sie hier, um jetzt zu sehen.

Anwendungsfälle:

  1. Der Hauptthread in Android besteht aus Looper und Handlers . Daher ist das Verständnis davon unerlässlich, um eine nicht blockierte reaktionsschnelle Benutzeroberfläche zu erstellen.
  2. Die Entwickler, die Bibliotheken schreiben, können es sich aufgrund der Bibliotheksgröße nicht leisten, Bibliotheken von Drittanbietern zu verwenden. Für sie ist es daher am besten, die vorhandenen verfügbaren Ressourcen zu nutzen. Das Schreiben einer eigenen Lösung für die IT erreicht möglicherweise nicht immer dieses Maß an Effizienz und Optimierung.
  3. Das gleiche Argument kann auch für Unternehmen / Einzelpersonen verwendet werden, die SDKs versenden. Die Clients können unterschiedliche Implementierungen haben, aber alle verwenden die gängigen Android Framework-APIs.
  4. Wenn Sie sie vollständig verstehen, können Sie dem Android SDK und den Paketklassen im Allgemeinen besser folgen.

Beginnen wir die Erkundung / Überarbeitung mit einem Fragebogen.

Ich erwarte, dass der Leser das grundlegende Verständnis von Java-Threads hat. Wenn Sie möchten, erhalten Sie einen schnellen Überblick über Java Thread und Runnable.

Was ist das Problem mit Java Thread?

Java-Threads werden nur einmal verwendet und sterben nach Ausführung der run-Methode.

Können wir es verbessern?

Der Faden ist ein zweischneidiges Schwert. Wir können die Ausführung beschleunigen, indem wir die Aufgaben auf Ausführungsthreads verteilen, aber auch verlangsamen, wenn Threads im Übermaß vorhanden sind. Die Thread-Erstellung an sich ist ein Overhead. Die beste Option ist also, eine optimale Anzahl von Threads zu haben und diese für die Ausführung von Aufgaben wiederzuverwenden.

Modell für gewinde wiederverwendbarkeit:

  1. Der Thread wird in einer Schleife über die run() -Methode am Leben erhalten.
  2. Die Aufgabe wird von diesem Thread seriell ausgeführt und in einer Warteschlange (MessageQueue) verwaltet.
  3. Der Thread muss beendet werden, wenn er fertig ist.

Was macht der Android?

Das obige Modell ist im Android über Looper, Handler und HandlerThread implementiert. Das System kann als Fahrzeug visualisiert werden, wie auf dem Cover des Artikels.

  1. MessageQueue ist eine Warteschlange mit Aufgaben namens Nachrichten, die verarbeitet werden sollen.
  2. Handler enqueues Aufgabe in der MessageQueue mit Looper und führt sie auch aus, wenn die Aufgabe aus der MessageQueue kommt.
  3. Looper ist ein Worker, der einen Thread am Leben erhält, MessageQueue durchläuft und Nachrichten an den entsprechenden handler sendet, um sie zu verarbeiten.
  4. Schließlich wird Thread durch Aufrufen der quit() -Methode von Looper beendet.

Ein Thread kann nur einen eindeutigen Looper und viele eindeutige Handler haben.

Erstellen von Looper und MessageQueue für einen Thread:

Ein Thread erhält nach seiner Ausführung Looper und MessageQueue, indem er Looper.prepare() aufruft. Looper.prepare() identifiziert den aufrufenden Thread, erstellt ein Looper – und MessageQueue -Objekt und verknüpft thread mit ihnen in der ThreadLocal -Speicherklasse. Looper.loop()muss aufgerufen werden, um den zugehörigen Looper zu starten. Ebenso muss looper explizit durch looper.quit() beendet werden.

class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; Looper.loop(); } }

Handler für einen Thread erstellen:

A Handler wird implizit mit dem Thread verknüpft, der ihn über Threads Looper instanziiert, aber wir können ihn explizit an einen Thread binden, indem wir den Thread übergeben looper im Konstruktor des Handler .

handler = new Handler() {@Overridepublic void handleMessage(Message msg) { // process incoming messages here // this will run in the thread, which instantiates it }};

Senden von Nachrichten an die MessageQueue über Handler kann durch zwei Modi erfolgen:

  1. Message: Es ist eine Klasse, die verschiedene nützliche Methoden zum Umgang mit Nachrichtendaten definiert. Um ein Objekt zu senden, setzen wir die Variable obj.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);

Eine detaillierte Übersicht der Klasse Message finden Sie hier: https://developer.android.com/reference/android/os/Message.html

Runnable: Ein Runnable kann auch im MessageQueue gepostet werden. Beispiel: Posten und Ausführen einer Aufgabe im Hauptthread.

new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() { // this will run in the main thread }});

Im obigen Beispiel erstellen wir eine Handler und geben Looper an, die dem Hauptthread zugeordnet ist. Dadurch wird dieser Handler dem Hauptthread zugeordnet. Wenn wir die Runnable , wird sie in der MessageQueue des Hauptthreads in die Warteschlange gestellt und dann im Hauptthread ausgeführt.

Handler ist in der Lage, Nachrichten auf vielfältige Weise zu manipulieren, was hier zu finden ist: https://developer.android.com/reference/android/os/Handler.html

Das Erstellen eines eigenen Threads und das Bereitstellen von Lopper und MessageQueue ist nicht der richtige Weg, um das Problem zu lösen. Daher hat Android HandlerThread (Unterklasse von Thread) bereitgestellt, um den Prozess zu rationalisieren. Intern macht es die gleichen Dinge, die wir getan haben, aber auf robuste Weise. Verwenden Sie also immer HandlerThread .

Eine der Möglichkeiten, den HandlerThread zu erstellen, besteht darin, ihn in Unterklassen zu unterteilen, und die meiste Zeit werden Sie diese Methode verwenden.

private class MyHandlerThread extends HandlerThread { Handler handler; public MyHandlerThread(String name) { super(name); } @Override protected void onLooperPrepared() { handler = new Handler(getLooper()) { @Override public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; }}

Hinweis: Wir haben den Handler instanziiert, wenn onLooperPrepared() aufgerufen wird. Das Handler kann also mit dem Looper verknüpft werden.

  1. Looper wird nur vorbereitet, nachdem Handlerthreads start() aufgerufen wurde, dh nachdem der Thread ausgeführt wurde.
  2. A Handler kann nur mit a HandlerThread verknüpft werden, nachdem Looper vorbereitet wurde.

Andere Möglichkeit, den HandlerThread zu erstellen:

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");handlerThread.start();Handler handler = new Handler(handlerThread.getLooper());

Hinweis: HandlerThread muss myHandlerThread.quit() aufrufen, um die Ressourcen freizugeben und die Ausführung des Threads zu stoppen.

Ich würde vorschlagen, die obigen Codes zu üben, damit Sie ihre kleinen Details verstehen können.

Ich habe ein Beispielprojekt für Post Office Simulation erstellt. Post Office basiert auf HandlerThread und Kunden kommunizieren mit Hilfe der Post. Eine Simulatorklasse erstellt einige Client-Bots und delegiert ihre Kommunikation an die MainActivity , die sie in einem Live-Feed rendert.

Der Link zu diesem Beispiel

Ich habe auch ein Video-Tutorial zu diesem Thema erstellt, und ich empfehle dringend, es zu sehen. Klicken Sie hier, um jetzt zu sehen.

Lassen Sie uns auch Freunde auf Twitter, Linkedin, Github und Facebook werden.

Lernen ist eine Reise, lass uns zusammen lernen!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.