annulation d'un processus handler.postdelayed

259

J'utilise handler.postDelayed()pour créer une période d'attente avant la prochaine étape de mon application. Pendant la période d'attente, j'affiche une boîte de dialogue avec une barre de progression et un bouton Annuler .

Mon problème est que je ne peux pas trouver un moyen d' annuler la tâche postDelayed avant la fin du temps.

Ron
la source
J'espère que cette aide essentielle gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity en tant que lanceur d'écran avec gestionnaire et fonction exécutable, la page Runnable run to login ou la page de flux avec l'utilisateur de connexion de préférence de base avec firebase.
Mubin

Réponses:

479

Je fais cela pour publier un runnable retardé:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

Et ceci pour le supprimer: myHandler.removeCallbacks(myRunnable);

Varun
la source
74
Si vous pouvez vous permettre d'annuler tous les rappels et messages sur le gestionnaire et que vous ne voulez pas avoir à conserver les références à l'exécutable, le troisième point de la réponse acceptée à cette question est une autre alternative qui semble fonctionner pour mon cas de toute façon: stackoverflow. com / questions / 11299440 /… (appelant essentiellement myHandler.removeCallbacksAndMessages (null);)
Mick
removeCallbacksAndMessages peut faire l'affaire, mais personnellement je préfère avoir le contrôle sur les runnables planifiés. Instancier et gérer une paire de Runnables ne tuera pas les performances de votre application; sinon, si vous avez besoin de plus de deux ou trois Runnables, vous aurez peut-être besoin de quelque chose de plus puissant, à mon humble avis.
andrea.rinaldi
59

Dans le cas où plusieurs runnables internes / anonymes sont passées au même gestionnaire et que vous souhaitez tout annuler lors d'une même utilisation d'événement

handler.removeCallbacksAndMessages(null);

Selon la documentation,

Supprimez tous les messages en attente de rappels et les messages envoyés dont l'obj est un jeton. Si le jeton est nul, tous les rappels et messages seront supprimés.

Mani
la source
Cela supprimera tous les rappels exécutables une fois. Sinon, appelez removeCallbacks(callback) pour supprimer un rappel spécifique
FindOutIslamNow
18

Une autre façon consiste à gérer le Runnable lui-même:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
la source
14
BooleanCancelMember ne devrait-il pas être définitif, ce qui signifie qu'il ne peut pas être modifié et donc inutile à cette fin?
stealthcopter
9
@stealthcopter non, ce n'est pas obligatoire.
Benoit Jadinon
7
@pablisco Il ne doit pas être définitif même si Runnable est anonyme. Il peut être membre de la classe englobante.
Martin
6
Ne pas voter contre cela, mais soyez prudent. Avec cette approche, si plusieurs Runnables sont affichés en retard, vous pouvez rencontrer des conditions de course désagréables. Cela n'annule pas le Runnable, donc si ce code sera exécuté ou non dépend de la valeur de booleanCancelMember au moment spécifique pour chaque Runnable publié. Ce qui peut rapidement devenir imprévisible.
Dennis K
1
Si Runnable n'est PAS annonymous, cela signifie que j'ai une référence ( rdans ce cas), ce qui signifie que je peux l'utiliser myHandler.removeCallbacks(r);. Si Runnable est anonyme, le drapeau sera un membre de la classe englobante, ce qui signifie que j'ai besoin d'une référence à cet objet pour changer le drapeau, ce qui signifie que je devrai de nouveau avoir de rtoute façon, ce qui signifie que je peux le faire myHandler.removeCallbacks(r);. Et si je le fais, myHandler.removeCallbacks(r);ce drapeau n'est pas du tout nécessaire. Suis-je en train de manquer quelque chose?
nacho4d
1

Voici une classe fournissant une méthode d'annulation pour une action retardée

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);
}}
Stéphane Padovani
la source
0

Cela a fonctionné pour moi lorsque j'ai appelé CancelCallBacks (ceci) à l'intérieur du postnable retardé en le remettant via un booléen

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);
        }
    }
};
Ramin Fallahzadeh
la source
3
Il n'y a pas de "CancelCallBacks" dans votre code. Peut-être parce que ça n'existe pas? :)
L'incroyable