annullamento di un processo handler.postdelayed


261

Sto usando handler.postDelayed()per creare un periodo di attesa prima che abbia luogo la fase successiva della mia app. Durante il periodo di attesa viene visualizzata una finestra di dialogo con barra di avanzamento e pulsante Annulla .

Il mio problema è che non riesco a trovare un modo per annullare l' attività postDelayed prima che sia trascorso il tempo.



Spero che questo gist aiuti gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity come Screen Launcher con handler e funzione eseguibile, Runnable run to login page o feed page with base preferenza login user with firebase.
Mubin

Risposte:


482

Lo faccio per pubblicare un runnable ritardato:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

E questo per rimuoverlo: myHandler.removeCallbacks(myRunnable);


74
Se puoi permetterti di annullare tutti i callback e i messaggi sul gestore e non vuoi dover mantenere i riferimenti all'eseguibile, il terzo punto nella risposta accettata a questa domanda è un'altra alternativa che sembra funzionare comunque per il mio caso: stackoverflow. com / questions / 11299440 /… (essenzialmente chiamando myHandler.removeCallbacksAndMessages (null);)
Mick

removeCallbacksAndMessages può fare il trucco, ma personalmente preferisco avere il controllo sui runnable pianificati. Istanziare e gestire un paio di Runnable non ucciderà le prestazioni dell'app; altrimenti, se hai bisogno di più di due o tre Runnable, potresti aver bisogno di qualcosa di più potente, imho.
andrea.rinaldi

62

Nel caso in cui siano stati passati più runnable interni / anonimi allo stesso gestore e si desidera annullare tutti allo stesso uso dell'evento

handler.removeCallbacksAndMessages(null);

Come da documentazione,

Rimuovi tutti i post in sospeso di callback e messaggi inviati il ​​cui oggetto è token. Se il token è nullo, tutti i callback e i messaggi verranno rimossi.


Questo rimuoverà una volta tutti i callback eseguibili. Altrimenti, chiama removeCallbacks(callback) per rimuovere una richiamata specifica
FindOutIslamNow

18

Un altro modo è gestire il Runnable stesso:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}

14
BooleanCancelMember non dovrebbe essere definitivo, il che significa che non può essere modificato e quindi inutile per questo scopo?
Stealthcopter

9
@stealthcopter no, non deve esserlo.
Benoit Jadinon

7
@pablisco Non deve essere definitivo anche se il Runnable è anonimo. Può essere un membro della classe di inclusione.
Martin

6
Non downvoting questo, ma fai attenzione. Con questo approccio, se più Runnable vengono postati in ritardo, potresti incorrere in condizioni di gara brutte. Questo non annulla il Runnable, quindi se quel codice verrà eseguito o meno dipende dal valore di booleanCancelMember nel momento specifico per ogni Runnable pubblicato. Che potrebbe diventare rapidamente imprevedibile.
Dennis K

1
Se Runnable NON è anonimo significa che ho un riferimento ad esso ( rin questo caso) il che significa che posso usare myHandler.removeCallbacks(r);. Se il Runnable è anonimo, il flag sarà un membro della classe che lo racchiude, il che significa che ho bisogno di un riferimento a quell'oggetto per cambiare il flag, il che significa che dovrò di nuovo avere rcomunque, il che significa che posso farlo myHandler.removeCallbacks(r);. E se lo sto facendo, myHandler.removeCallbacks(r);tale bandiera non è affatto necessaria. Mi sto perdendo qualcosa?
nacho4d

1

Ecco una classe che fornisce un metodo di annullamento per un'azione ritardata

public class DelayedAction {

private Handler _handler;
private Runnable _runnable;

/**
 * Constructor
 * @param runnable The runnable
 * @param delay The delay (in milli sec) to wait before running the runnable
 */
public DelayedAction(Runnable runnable, long delay) {
    _handler = new Handler(Looper.getMainLooper());
    _runnable = runnable;
    _handler.postDelayed(_runnable, delay);
}

/**
 * Cancel a runnable
 */
public void cancel() {
    if ( _handler == null || _runnable == null ) {
        return;
    }
    _handler.removeCallbacks(_runnable);
}}

0

Ha funzionato per me quando ho chiamato CancelCallBacks (questo) all'interno del post ritardato eseguibile consegnandolo tramite un booleano

Runnable runnable = new Runnable(){
    @Override
    public void run() {
        Log.e("HANDLER", "run: Outside Runnable");
        if (IsRecording) {
            Log.e("HANDLER", "run: Runnable");
            handler.postDelayed(this, 2000);
        }else{
            handler.removeCallbacks(this);
        }
    }
};

3
Non c'è "CancelCallBacks" nel codice. Forse perché non esiste? :)
L'incredibile Jan

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.