Beste Verwendung von HandlerThread gegenüber anderen ähnlichen Klassen

Lesezeit: 6 Minuten

Beste Verwendung von HandlerThread gegenuber anderen ahnlichen Klassen
Androidme

Ich versuche, den besten Anwendungsfall der Verwendung zu verstehen HandlerThread.

Laut Definition:

“Praktische Klasse zum Starten eines neuen Threads, der einen Looper hat. Der Looper kann dann verwendet werden, um Handler-Klassen zu erstellen. Beachten Sie, dass start() immer noch aufgerufen werden muss.”

Ich kann mich irren, aber eine ähnliche Funktionalität kann ich mit a erreichen Thread, Looper und Handler. Wann sollte ich also verwenden HandlerThread? Ein Beispiel wäre wirklich hilfreich.

  • Ich habe HandlerThread nie verwendet, aber vielleicht hilft dieser Beitrag – stackoverflow.com/questions/7462098/…

    – Tal Kanel

    9. August 2013 um 15:14 Uhr

  • @TalKanel: Danke für die Antwort. Ich habe diesen Beitrag überprüft, aber er spricht über den Nutzen von Executor gegenüber HandlerThread, dem ich voll und ganz zustimme. Meine Frage ist eher, was der beste Anwendungsfall für die Verwendung von HandlerThread ist

    – Androidme

    9. August 2013 um 15:20 Uhr

  • Dieser Beitrag geht auch auf diese Frage ein. Executoren sind flexibler, da sie einen Pool von Threads verwalten können. Mehrere Threads – Sie müssen einen Executor verwenden. Einzelner Thread – Sie können einen HandlerThread verwenden. Ich bin mir nicht sicher, ob es wichtig ist, da der Testamentsvollstrecker beide Situationen abdecken könnte. Wie ich es verstanden habe, können Sie mit einem HandlerThread nur einen Handler in einem Hintergrundthread erstellen – etwas, das ohnehin auf andere Weise möglich ist.

    – Rar

    9. August 2013 um 15:28 Uhr

  • Siehe meinen Kommentar hier – stackoverflow.com/questions/17897536/how-to-handle-tcp-data/…. Im Allgemeinen bevorzuge ich HandlerThreads durch die supereinfache Synchronisierung via MessageS. Allerdings kann es auch ein Engpass sein. Außerdem hindert Sie nichts daran, einen ExecutorService mit HandlerThreads zu verwenden. Ich habe schon mal eins geschrieben, es ist nicht so schwer.

    – Deljan

    9. August 2013 um 15:30 Uhr


  • @Rarw: Das war eigentlich meine Frage, ob wir Dinge auf andere Weise tun können, was nötig ist, um eine andere Klasse zu erstellen. Ich bin mir sicher, dass es in speziellen Szenarien einige Vorteile gibt, die ich kennen muss.

    – Androidme

    9. August 2013 um 15:50 Uhr

Beste Verwendung von HandlerThread gegenuber anderen ahnlichen Klassen
Alex Cohn

Hier ist ein Beispiel aus dem wirklichen Leben, wo HandlerThread wird handlich. Wenn Sie sich für Kamera-Vorschaurahmen registrieren, erhalten Sie diese onPreviewFrame() Rückrufen. Die Dokumentation erklärt das Dieser Rückruf wird bei dem Ereignis-Thread aufgerufen, von dem aus open(int) aufgerufen wurde.

Normalerweise bedeutet dies, dass der Rückruf im Hauptthread (UI) aufgerufen wird. Daher kann die Aufgabe, mit den riesigen Pixelarrays umzugehen, hängen bleiben, wenn Menüs geöffnet, Animationen animiert oder sogar Statistiken auf dem Bildschirm gedruckt werden.

Die einfache Lösung besteht darin, eine new HandlerThread() und delegieren Camera.open() zu diesem Thread (ich habe es durch post(Runnable)müssen Sie nicht implementieren Handler.Callback).

Beachten Sie, dass alle anderen Arbeiten mit der Kamera wie gewohnt erledigt werden können, Sie müssen sie nicht delegieren Camera.startPreview() oder Camera.setPreviewCallback() zum HandlerThread. Um auf der sicheren Seite zu sein, ich Warten für das Eigentliche Camera.open(int) zu vervollständigen, bevor ich mit dem Haupt-Thread fortfahre (oder welchen Thread auch immer zum Aufrufen verwendet wurde Camera.open() vor der Änderung).


Also, wenn Sie mit Code beginnen

try {
    mCamera = Camera.open(1);
}
catch (RuntimeException e) {
    Log.e(LOG_TAG, "failed to open front camera");
}
// some code that uses mCamera immediately

erst extrahieren wie es ist in eine private Methode:

private void oldOpenCamera() {
    try {
        mCamera = Camera.open(1);
    }
    catch (RuntimeException e) {
        Log.e(LOG_TAG, "failed to open front camera");
    }
}

und statt anzurufen oldOpenCamera() einfach verwenden newOpencamera():

private void newOpenCamera() {
    if (mThread == null) {
        mThread = new CameraHandlerThread();
    }

    synchronized (mThread) {
        mThread.openCamera();
    }
}
private CameraHandlerThread mThread = null;
private static class CameraHandlerThread extends HandlerThread {
    Handler mHandler = null;

    CameraHandlerThread() {
        super("CameraHandlerThread");
        start();
        mHandler = new Handler(getLooper());
    }

    synchronized void notifyCameraOpened() {
        notify();
    }

    void openCamera() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                oldOpenCamera();
                notifyCameraOpened();
            }
        });
        try {
            wait();
        }
        catch (InterruptedException e) {
            Log.w(LOG_TAG, "wait was interrupted");
        }
    }
}

Beachten Sie, dass das Ganze benachrichtigen()Warten() Inter-Thread-Kommunikation ist nicht erforderlich, wenn Sie nicht darauf zugreifen mKamera im Originalcode sofort nach dem Öffnen.

Aktualisieren: Hier wird der gleiche Ansatz auf den Beschleunigungssensor angewendet: Acclerometer Sensor in Separate Thread

  • Wo würden Sie die Kamera dann schließen?

    – Mathias

    24. Februar 2014 um 8:13 Uhr

  • @Matthias: Das ist eine gute Frage. Wenn Ihr Anwendungsfall dies zulässt, lassen Sie die Kamera los Activity.onPause() – zuallererst, weil dies die ist nur Rückruf dass Ihre Aktivität garantiert vom System erhalten wird, gemäß der Aktivitätslebenszyklus. Aber es gibt Fälle, in denen Sie die Kamera verwenden können nach dem onPause(). In einem solchen Fall brauchen Sie nur wenige Orte, um in verschiedenen Szenarien anmutig zu sein.

    – Alex Cohn

    24. Februar 2014 um 13:56 Uhr

  • Das )} Schließen des neuen Runnable soll })

    – Reich

    23. März 2014 um 7:17 Uhr

  • @Praveen sicher, “statisch” ist in diesem Zusammenhang nichts Heiliges

    – Alex Cohn

    22. Dezember 2014 um 19:17 Uhr

  • @Praveen: Das können Sie in Ihrer Überschreibung tun notify()

    – Alex Cohn

    26. Dezember 2014 um 21:05 Uhr

1646543587 156 Beste Verwendung von HandlerThread gegenuber anderen ahnlichen Klassen
Roh

Hier ist ein Link zum Quellcode für HandlerThread und Schleifer.

Wenn Sie sich die beiden ansehen, werden Sie sehen, dass a HandlerThread ist genau das, was es verspricht – ein bequemer Weg, um damit zu beginnen Thread das hat ein Looper. Warum gibt es das? Weil Threads haben standardmäßig keine Nachrichtenschleife. Die HandlerThread ist nur eine einfache Möglichkeit, eine zu erstellen, die dies tut. Könntest du diese Funktion mit duplizieren Handler, Threadund Looper – nach dem Quellcode zu urteilen – lautet die Antwort ja.

Ein Executor ist anders. Ein Executor nimmt eingereichte ausführbare Aufgaben und – ratet mal – führt sie aus. Warum ist das notwendig? Es erlaubt Ihnen die Ausführung der Aufgabe von ihrem eigentlichen Inhalt zu entkoppeln. Wann würden Sie dies verwenden? Angenommen, Sie hatten eine Situation, in der mehrere Aufgaben gleichzeitig ausgeführt werden mussten. Sie können wählen, indem Sie ein verwenden Executor, um sie alle in einem einzigen Thread auszuführen, sodass sie seriell ausgeführt werden. Oder Sie könnten einen festen Thread-Pool verwenden, sodass einige, aber nicht alle gleichzeitig ausgeführt werden. In beiden Fällen ist der Inhalt der Aufgabe – dh was sie tatsächlich tut – von der Art und Weise, wie sie ausgeführt wird, getrennt.

  • Ich finde deine Unterscheidung ungenau. Sie können auch Aufgaben zur Ausführung über Handler.postRunnable senden. Tatsächlich können Sie einen ExecutorService erstellen, der nur HandlerThreads verwendet, indem Sie einfach die Methoden ThreadFactory und submit() ändern. Es ist die Thread-übergreifende Kommunikation, die mit HandlerThreads einfacher wird, nicht das Senden von Aufgaben.

    – Deljan

    10. August 2013 um 13:58 Uhr

  • Ich war wohl unklar. Ich wollte nicht andeuten, dass die Ausführung von Aufgaben mit einem Executor einfacher ist. Vielmehr ist der Zweck eines Executors darauf ausgelegt, nur die Ausführung dieser Aufgaben zu übernehmen. Ein HandlerThread dient einem anderen Zweck. Ich werde es später bearbeiten.

    – Rar

    10. August 2013 um 14:27 Uhr

953100cookie-checkBeste Verwendung von HandlerThread gegenüber anderen ähnlichen Klassen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy