Wie entferne ich eine ausführbare Datei aus einem von postDelayed hinzugefügten Handlerobjekt?

70

Ich habe eine "offene" Animation und verwende Handler.postDelayed(Runnable, delay), um nach einer kurzen Verzögerung eine "geschlossene" Animation auszulösen . In der Zeit zwischen Öffnen und Schließen wird möglicherweise eine andere Animation durch einen Klick ausgelöst.

Meine Frage ist, wie würde ich die "Schließen" -Animation im Handler abbrechen ?

Bruce Lee
quelle
Seien Sie vorsichtig mit dieser Antwort, wenn Sie Kotlin verwenden: stackoverflow.com/a/30905295/2736039 , ich habe das versucht und bin auf dieses Problem gestoßen
Ultimo_m

Antworten:

99

Verwenden Sie einfach die removeCallbacks(Runnable r)Methode.

Cristian
quelle
10
Ist es möglich, Rückrufe für anonyme ausführbare Dateien zu entfernen?
Bruce Lee
10
Ich glaube nicht ... Sie müssen nicht anonyme verwenden. Andernfalls können Sie sie in Zukunft nicht mehr referenzieren.
Cristian
3
Siehe die Antwort von @ NameSpace. Sie können ausstehende ausführbare Dateien entfernen, wenn Sie die ausführbare Datei mit einem Token veröffentlichen. Oder Sie können die Methode von Daniel L. verwenden, um alle Rückrufe / Nachrichten mit einem Null-Token zu entfernen.
Vman
Gibt es Empfehlungen zum Entfernen bestimmter Rückrufe für APIs, bei denen removeCallbacks (Runnable r) nicht verfügbar war?
GOM1
Entfernt dies alle Vorkommen der Instanz? Weil ich es mehrmals mit unterschiedlichen Verzögerungszeiten
poste
96

Die Antwort von Cristian ist korrekt, aber im Gegensatz zu den Kommentaren in der Antwort können Sie Rückrufe für anonyme RunnablesAnrufe entfernenremoveCallbacksAndMessages(null);

Wie hier angegeben :

Entfernen Sie alle ausstehenden Posts von Rückrufen und gesendeten Nachrichten, deren Objekt ein Token ist. Wenn das Token null ist, werden alle Rückrufe und Nachrichten entfernt .

Daniel L.
quelle
5
Ich möchte nur darauf hinweisen, dass dieses Verhalten anders ist, egal ob Sie es mit einer Handleroder einer ViewKlasse zu tun haben . In einer ViewKlasse (und möglicherweise nach 4.0?) Müssen Sie dasselbe RunnableObjekt verwenden, um die Aufgabe abzubrechen, während bei einer HandlerKlasse einfach alle abgebrochen werden, wenn Sie bestehen null. Die Frage gibt jedoch a an, Handlersodass Ihre Antwort korrekt ist.
Andre
1
Ja wirklich!! danke .. hatte da etwas lauffähiges und removeCallbacks hat einfach nichts gemacht !!!!! aber das hat wirklich geklappt :) thx
cV2
17

Dies ist eine späte Antwort, aber hier ist eine andere Methode, wenn Sie nur eine bestimmte Kategorie von Runnables aus dem Handler entfernen möchten (dh im Fall von OP entfernen Sie einfach die Schließen-Animation und lassen andere Runnables in der Warteschlange):

    int firstToken = 5;
    int secondToken = 6;

    //r1 to r4 are all different instances or implementations of Runnable.  
    mHandler.postAtTime(r1, firstToken, 0);
    mHandler.postAtTime(r2, firstToken, 0);
    mHandler.postAtTime(r3, secondToken, 0);

    mHandler.removeCallbacksAndMessages(firstToken);

    mHandler.postAtTime(r4, firstToken, 0);

Der obige Code führt nur "r3" und dann nur "r4" aus. Auf diese Weise können Sie eine bestimmte Kategorie von Runnables entfernen, die von Ihrem Token definiert wurden, ohne Verweise auf die Runnables selbst enthalten zu müssen.

Hinweis: Der Quellcode vergleicht Token nur mit dem Operanden "==" (er ruft nicht .equals () auf). Verwenden Sie daher am besten Ints / Integer anstelle von Zeichenfolgen für das Token.

NameSpace
quelle
Ich habe Ihre Antwort gesehen und bin von stringzu gewechselt intund hatte dann einen Tag lang diesen Fehler: D stackoverflow.com/q/62405834/2736039
Ultimo_m
Dies wird in Kotlin für int> 127 nicht funktionieren, nur diesen Kommentar hier als Hinweis für zukünftige Leser zu
hinterlassen
10

Wenn Sie eine Rekursion verwenden, können Sie dies erreichen, indem Sie "this" übergeben. Siehe Code unten.

public void countDown(final int c){
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            aq.id(R.id.timer).text((c-1)+"");
            if(c <= 1){
                aq.id(R.id.timer).gone();
                mHandler.removeCallbacks(this);
            }else{
                countDown(c-1);
            }
        }
    }, 1000);
}

In diesem Beispiel wird der Text einer Textansicht (Timer) jede Sekunde heruntergezählt. Sobald 0 erreicht ist, wird die Textansicht von der Benutzeroberfläche entfernt und der Countdown deaktiviert. Dies ist nur für jemanden nützlich, der Rekursion verwendet, aber ich bin hier angekommen, um danach zu suchen, also veröffentliche ich meine Ergebnisse.

Robisaks
quelle