Was ist der Zweck von Looper und wie wird es verwendet?

454

Ich bin neu in Android. Ich möchte wissen, was die LooperKlasse 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 Looperund wenn möglich auch ein einfaches Beispiel gibt?

Khawar Raza
quelle
7
Ich habe gerade eine außerordentlich gründliche und klare Erklärung für Looper und seine Verwendung in Safari Books Online gefunden. Leider vermute ich, dass der Zugang nur für eine begrenzte Zeit kostenlos ist. safaribooksonline.com/library/view/efficient-android-threading/…
Joe Lapp
1
Für Android-Artikel und Referenzseiten müssen Sie einen vorherigen Artikel haben und verstehen, bevor Sie den aktuellen Artikel erfassen können. Ich schlage vor, dass Sie die Artikel zu Aktivitäten und Diensten in den API-Handbüchern lesen und dann Handler und Looper lesen. Es hilft auch, wenn Sie verstehen, was ein Thread ist (kein Android-Thread, sondern ein Thread im Allgemeinen ... zB POSIX).
FutureSci
1
Ich fand diesen Artikel nützlich: codetheory.in/…
Herman

Antworten:

396

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 der loop()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.

class LooperThread extends Thread {
      public Handler mHandler;

      @Override
      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }
Dharmendra
quelle
17
Eine AsyncTask ist für diesen Zweck besser und weniger komplex, da sie die gesamte Thread-Verwaltung einschließt.
Fernando Gallego
4
Sollte @Override Annotationen vor den Methoden run () und handleMessage () haben
Andrew Mackenzie
5
Aus der Dokumentation geht hervor, dass Sie looper.quit aufrufen müssen. In Ihrem obigen Code wird Looper.loop auf unbestimmte Zeit blockiert.
AndroidDev
2
So beenden Sie eine Schleife. Ich meine, wo Looper.quit () in das obige Codebeispiel aufgenommen werden soll?
Seenu69
6
Ich denke, es wäre besser, HandlerThread zu verwenden , eine praktische Klasse für einen Thread mit einem Looper.
Nimrod Dayan
287

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.

김준호
quelle
26
Dies ist die einzige Antwort, die tatsächlich erklärt, warum die Looper-Klasse jemals verwendet werden würde. Ich bin mir nicht sicher, warum es nicht die beste Antwort ist. Die drei höher bewerteten Antworten erklären nichts.
Andrew Koster
4
@AK. Deshalb habe ich diese Antwort hinzugefügt, obwohl es zu spät schien. Ich bin froh, dass meine Antwort Ihnen geholfen hat! :)
10
1
@ Hey-men-whatsup Ja
6
1
Bevor ich das las, war ich wie "Looper ???" und jetzt "Oh ja, lass uns darüber diskutieren". Danke Mann, tolle Antwort :)
umerk44
Schnelle Frage. Sie haben angegeben, dass im Haupt-Thread, nachdem alle UI-Elemente herausgezogen wurden, der Ruhezustand aktiviert wird. Angenommen, der Benutzer interagiert mit einer Schaltfläche auf dem Bildschirm. Wird dieser Schaltflächenklick nicht einmal in eine Hauptwarteschlange gestellt, wird er von einem Objekt an die richtige Aktivität gesendet, und der Hauptthread für diese Aktivität wird aktiviert und ausgeführt den Code für im Rückruf für diese Schaltfläche klicken?
CapturedTree
75

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:

class SampleLooper extends Thread {
@Override
public void run() {
  try {
    // preparing a looper on current thread     
    // the current thread is being detected implicitly
    Looper.prepare();

    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();

    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  } 
}
}

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.

handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
    }
});

Auf dem UI-Thread haben wir einen impliziten Looper, mit dem wir die Nachrichten auf dem UI-Thread verarbeiten können.

user2834274
quelle
es wird keinen UI-Prozess sperren, ist es wahr?
Gumuruh
4
Vielen Dank für die Aufnahme eines Beispiels zum Posten von "Jobs" in der Warteschlange
Peter Lillevold
Dies erklärt nicht, warum man diese Klasse verwenden würde, sondern nur wie.
Andrew Koster
33

Android Looperist ein Wrapper anhängen MessageQueuezu Threadund verwaltet Queue - Verarbeitung. In der Android-Dokumentation sieht es sehr kryptisch aus, und häufig Loopertreten 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 LooperLebenszyklus, seine Verwendung und die Verwendung von Looperin erklärtHandler

Geben Sie hier die Bildbeschreibung ein

Looper = Thread + MessageQueue

user542954
quelle
3
Dies erklärt nicht, warum man diese Klasse verwenden würde, sondern nur wie.
Andrew Koster
14

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

ahmadalibaloch
quelle
7

Ein Looper verfügt über einen synchronized MessageQueue, der zum Verarbeiten von Nachrichten verwendet wird, die in die Warteschlange gestellt werden.

Es implementiert ein Threadbestimmtes Speichermuster.

Nur eine Looperpro Thread. Key - Verfahren umfassen prepare(), loop()und quit().

prepare()Initialisiert den Strom Threadals Looper. prepare()ist eine staticMethode, die die ThreadLocalKlasse wie unten gezeigt verwendet.

   public static void prepare(){
       ...
       sThreadLocal.set
       (new Looper());
   }
  1. prepare() muss explizit aufgerufen werden, bevor die Ereignisschleife ausgeführt wird.
  2. 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 Zielhandler
  3. quit()fährt die Ereignisschleife herunter. Die Schleife wird nicht beendet, sondern eine spezielle Nachricht in die Warteschlange gestellt

Looperkann in Threadmehreren Schritten programmiert werden

  1. Erweitern Thread

  2. Aufruf Looper.prepare()zum Initialisieren von Thread alsLooper

  3. Erstellen Sie eine oder mehrere Handler, um die eingehenden Nachrichten zu verarbeiten

  4. Aufruf Looper.loop()zur Verarbeitung von Nachrichten, bis die Schleife dazu aufgefordert wird quit().
Das Ö
quelle
5

Die Lebensdauer von Java Thread ist nach Abschluss der run()Methode abgelaufen. Der gleiche Thread kann nicht erneut gestartet werden.

Looper verwandelt normal Threadin eine Nachrichtenschleife. Schlüsselmethoden von Loopersind:

void prepare ()

Initialisieren Sie den aktuellen Thread als Looper. Auf diese Weise können Sie Handler erstellen, die dann auf diesen Looper verweisen, bevor Sie die Schleife starten. Stellen Sie sicher, dass Sie loop () aufrufen, nachdem Sie diese Methode aufgerufen haben, und beenden Sie sie, indem Sie quit () aufrufen.

void loop ()

Führen Sie die Nachrichtenwarteschlange in diesem Thread aus. Rufen Sie unbedingt quit () auf, um die Schleife zu beenden.

void quit()

Verlässt den Looper.

Bewirkt, dass die loop () -Methode beendet wird, ohne dass weitere Nachrichten in der Nachrichtenwarteschlange verarbeitet werden.

Dieser Mindorks-Artikel von Janishar erklärt die Kernkonzepte auf nette Weise.

Geben Sie hier die Bildbeschreibung ein

Looperist einem Thread zugeordnet. Wenn Sie brauchenLooper UI-Thread , Looper.getMainLooper()wird der zugehörige Thread zurückgegeben.

Sie müssen Loopermit einem verknüpft sein Handler zugeordnet sein .

Looper, Handler Und HandlerThreadsind der Weg des Android, die Probleme der asynchronen Programmierung zu lösen.

Sobald Sie haben Handler, können Sie unten APIs aufrufen.

post (Runnable r)

Bewirkt, dass Runnable r zur Nachrichtenwarteschlange hinzugefügt wird. Die ausführbare Datei wird auf dem Thread ausgeführt, an den dieser Handler angehängt ist.

boolean sendMessage (Message msg)

Schiebt eine Nachricht nach allen ausstehenden Nachrichten vor der aktuellen Zeit an das Ende der Nachrichtenwarteschlange. Es wird in handleMessage (Message) in dem an diesen Handler angehängten Thread empfangen.

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 HandlerThreadist nützlich. Sie können erhalten LooperObjekt aus HandlerThreadund erstellen HandleraufHandlerThread statt Haupt - Thread.

Der HandlerThread- Code sieht folgendermaßen aus:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

Beispielcode finden Sie im folgenden Beitrag:

Android: Toast in einem Thread

Ravindra Babu
quelle
5

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: Geben Sie hier die Bildbeschreibung ein

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

Wenn eine Anwendung gestartet wird, erstellt das System einen Ausführungsthread für die Anwendung mit dem Namen "main". Dieser Thread ist sehr wichtig, da er für das Versenden von Ereignissen an die entsprechenden Widgets der Benutzeroberfläche zuständig ist, einschließlich des Zeichnens von Ereignissen.

Geben Sie hier die Bildbeschreibung ein

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

Die Antwort lautet Looper-Klasse : Looper ist eine Klasse, die verwendet wird, um einen Thread am Leben zu erhalten und eine Nachrichtenwarteschlange zu verwalten, um Aufgaben in diesem Thread auszuführen.

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.

Der Zweck von Looper besteht darin, einen Thread am Leben zu halten und auf den nächsten Zyklus des Eingabeobjekts Messagezu warten , um eine Berechnung durchzuführen, die andernfalls nach dem ersten Ausführungszyklus zerstört wird.

Wenn Sie genauer wissen möchten, wie Looper die MessageObjektwarteschlange verwaltet , können Sie sich den Quellcode von Folgendem ansehen Looperclass:

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/Looper.java

Im Folgenden finden Sie ein Beispiel dafür, wie Sie eine Klasse erstellen Looper Threadund mit ihr kommunizieren ActivitykönnenLocalBroadcast

class LooperThread : Thread() {

    // sendMessage success result on UI
    private fun sendServerResult(result: String) {
        val resultIntent = Intent(ServerService.ACTION)
        resultIntent.putExtra(ServerService.RESULT_CODE, Activity.RESULT_OK)
        resultIntent.putExtra(ServerService.RESULT_VALUE, result)
        LocalBroadcastManager.getInstance(AppController.getAppController()).sendBroadcast(resultIntent)
    }

    override fun run() {
        val looperIsNotPreparedInCurrentThread = Looper.myLooper() == null

        // Prepare Looper if not already prepared
        if (looperIsNotPreparedInCurrentThread) {
            Looper.prepare()
        }

        // Create a handler to handle messaged from Activity
        handler = Handler(Handler.Callback { message ->
            // Messages sent to Looper thread will be visible here
            Log.e(TAG, "Received Message" + message.data.toString())

            //message from Activity
            val result = message.data.getString(MainActivity.BUNDLE_KEY)

            // Send Result Back to activity
            sendServerResult(result)
            true
        })

        // Keep on looping till new messages arrive
        if (looperIsNotPreparedInCurrentThread) {
            Looper.loop()
        }
    }

    //Create and send a new  message to looper
    fun sendMessage(messageToSend: String) {
        //Create and post a new message to handler
        handler!!.sendMessage(createMessage(messageToSend))
    }


    // Bundle Data in message object
    private fun createMessage(messageToSend: String): Message {
        val message = Message()
        val bundle = Bundle()
        bundle.putString(MainActivity.BUNDLE_KEY, messageToSend)
        message.data = bundle
        return message
    }

    companion object {
        var handler: Handler? = null // in Android Handler should be static or leaks might occur
        private val TAG = javaClass.simpleName

    }
}

Verwendung :

 class MainActivity : AppCompatActivity() {

    private var looperThread: LooperThread? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start looper thread
        startLooperThread()

        // Send messages to Looper Thread
        sendMessage.setOnClickListener {

            // send random messages to looper thread
            val messageToSend = "" + Math.random()

            // post message
            looperThread!!.sendMessage(messageToSend)

        }   
    }

    override fun onResume() {
        super.onResume()

        //Register to Server Service callback
        val filterServer = IntentFilter(ServerService.ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(serverReceiver, filterServer)

    }

    override fun onPause() {
        super.onPause()

        //Stop Server service callbacks
     LocalBroadcastManager.getInstance(this).unregisterReceiver(serverReceiver)
    }


    // Define the callback for what to do when data is received
    private val serverReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val resultCode = intent.getIntExtra(ServerService.RESULT_CODE, Activity.RESULT_CANCELED)
            if (resultCode == Activity.RESULT_OK) {
                val resultValue = intent.getStringExtra(ServerService.RESULT_VALUE)
                Log.e(MainActivity.TAG, "Server result : $resultValue")

                serverOutput.text =
                        (serverOutput.text.toString()
                                + "\n"
                                + "Received : " + resultValue)

                serverScrollView.post( { serverScrollView.fullScroll(View.FOCUS_DOWN) })
            }
        }
    }

    private fun startLooperThread() {

        // create and start a new LooperThread
        looperThread = LooperThread()
        looperThread!!.name = "Main Looper Thread"
        looperThread!!.start()

    }

    companion object {
        val BUNDLE_KEY = "handlerMsgBundle"
        private val TAG = javaClass.simpleName
    }
}

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 ThreadPoolExecutornur bis zu 5 Async-Aufgaben zulassen .

  • IntentServicessind auch für Hintergrundaufgaben konzipiert, mit denen Sie etwas länger LocalBroadcastkommunizieren können Activity. 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 tun while(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.

Hitesh Sahu
quelle
4

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:

HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);

und für eine vollständige Umsetzung

TacB0sS
quelle
3

Ein besseres Beispiel ist die Behandlung mehrerer Down- oder Upload-Elemente in einem Service .

Handlerund AsnycTaskwerden 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 Looperverarbeitet 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).

Thorsten
quelle
1

Was ist Looper?

VON DOKUMENTEN

Looper

LooperKlasse zum Ausführen einer Nachrichtenschleife für a thread. Threads sind standardmäßig keine Nachrichtenschleife zugeordnet. Um einen zu erstellen, rufen Sie prepare()den Thread auf, der die Schleife ausführen soll, und lassen Sie ihn dann loop()Nachrichten verarbeiten, bis die Schleife gestoppt ist.

  • A Looperist eine Nachrichtenbehandlungsschleife:
  • Ein wichtiges Merkmal von Looper ist, dass es dem Thread zugeordnet ist, in dem der Looper erstellt wird
  • Die Looper-Klasse verwaltet eine MessageQueue, die eine Listennachricht enthält. Ein wichtiges Merkmal von Looper ist, dass es dem Thread zugeordnet ist, in dem der Looper erstellt wird.
  • Das Looperheiß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önnte
  • Android Looperist 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.

Wie es funktioniert?

Geben Sie hier die Bildbeschreibung ein

Looper erstellen

Ein Thread erhält ein Looperund MessageQueuedurch Aufrufen Looper.prepare()nach seiner Ausführung. Looper.prepare()Identifiziert den aufrufenden Thread, erstellt einen Looper und ein MessageQueueObjekt und ordnet den Thread zu

BEISPIELCODE

class MyLooperThread extends Thread {

      public Handler mHandler; 

      public void run() { 

          // preparing a looper on current thread  
          Looper.prepare();

          mHandler = new Handler() { 
              public void handleMessage(Message msg) { 
                 // process incoming messages here
                 // this will run in non-ui/background thread
              } 
          }; 

          Looper.loop();
      } 
  }

Weitere Informationen finden Sie unten im Beitrag

Nilesh Rathod
quelle
ausgezeichnet, ich habe die Mechanik verstanden. danke
Serg Burlaka