web-dev-qa-db-fra.com

Comment supprimer tous les rappels d'un gestionnaire?

J'ai un gestionnaire de ma sous-activité qui a été appelée par le principal Activité . Ce gestionnaire est utilisé par les sous-classes pour postDelay certains Runnables, et je ne peux pas les gérer. Maintenant, dans l'événement onStop, je dois les supprimer avant de terminer l'activité (j'ai quand même appelé finish(), mais il appelle encore et encore). Est-il possible de supprimer tous les rappels d'un gestionnaire?

207
Luke Vo

Selon mon expérience, cela a très bien fonctionné!

handler.removeCallbacksAndMessages(null);

Dans la documentation de removeCallbacksAndMessages, il est indiqué ...

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

486
josh527

Pour toute instance Runnable spécifique, appelez Handler.removeCallbacks(). Notez qu’il utilise l’instance Runnable pour déterminer les rappels à annuler l’enregistrement. Ainsi, si vous créez une nouvelle instance à chaque publication, vous devez vous assurer que vous disposez des références exactes Runnable. annuler. Exemple:

Handler myHandler = new Handler();
Runnable myRunnable = new Runnable() {
    public void run() {
        //Some interesting task
    }
};

Vous pouvez appeler myHandler.postDelayed(myRunnable, x) pour envoyer un autre rappel dans la file d'attente des messages à d'autres endroits de votre code et supprimer tous les rappels en attente avec myHandler.removeCallbacks(myRunnable).

Malheureusement, vous ne pouvez pas simplement "effacer" l'intégralité de MessageQueue pour un Handler, même si vous faites une demande pour l'objet MessageQueue qui lui est associé car les méthodes d'ajout et de suppression d'éléments sont des packages. protected (seules les classes du package Android.os peuvent les appeler). Vous devrez peut-être créer une sous-classe Handler mince pour gérer une liste de Runnables au fur et à mesure de leur publication/exécution ... ou rechercher un autre paradigme pour transmettre vos messages entre chaque Activity

J'espère que ça t'as aidé!

19
Devunwired

Si vous ne disposez pas des références Runnable, lors du premier rappel, obtenez l'obj du message et utilisez removeCallbacksAndMessages () pour supprimer tous les rappels associés.

8
alphazero

Définir un nouveau gestionnaire et exécutable:

private Handler handler = new Handler(Looper.getMainLooper());
private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // Do what ever you want
        }
    };

Appel retardé:

handler.postDelayed(runnable, sleep_time);

Supprimez votre rappel de votre gestionnaire:

handler.removeCallbacks(runnable);
5
savepopulation

En fait, il y a un petit mais si important point ici. Vous devez définir une Handler et une Runnable pour la première fois. En fait, removeCallbacks(runnable) fonctionne correctement, mais si vous les définissez à chaque fois, vous ne pouvez pas les gérer.

Façon fausse:

    public class FooActivity extends Activity {
           private void handleSomething(){
                Handler handler = new Handler();
                Runnable runnable = new Runnable() {
                   @Override
                   public void run() {
                      doIt();
                  }
               };
              if(shouldIDoIt){
                  //doIt() works after 3 seconds.
                  handler.postDelayed(runnable, 3000);
              } else {
                  handler.removeCallbacks(runnable);
              }
           }

          public void onClick(View v){
              handleSomething();
          }
    } 

Si vous appelez la méthode onClick(..), vous n'arrêtez jamais la méthode doIt() en appelant avant l'appel. Parce que chaque fois crée new Handler et new Runnable instances. De cette façon, vous avez perdu les références nécessaires qui appartiennent à gestionnaire et à runnable les instances.

Vrai chemin:

 public class FooActivity extends Activity {
        Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                doIt();
            }
        };
        private void handleSomething(){
            if(shouldIDoIt){
                //doIt() works after 3 seconds.
                handler.postDelayed(runnable, 3000);
            } else {
                handler.removeCallbacks(runnable);
            }
       }

       public void onClick(View v){
           handleSomething();
       }
 } 

De cette façon, vous ne perdez pas de références réelles et removeCallbacks(runnable) fonctionne correctement.

La phrase clé est que 'définissez-les comme globaux dans votre Activity ou Fragment ce que vous utilisez'.

2
oguzhan

Comme josh527 a dit, handler.removeCallbacksAndMessages(null); peut fonctionner.
Mais pourquoi?
Si vous regardez le code source, vous pourrez le comprendre plus clairement. Il existe 3 types de méthodes pour supprimer les rappels/messages du gestionnaire (la MessageQueue):

  1. enlever par rappel (et jeton)
  2. enlever par message.what (et jeton)
  3. enlever par jeton

Handler.Java (laissez une méthode de surcharge

/**
 * Remove any pending posts of Runnable <var>r</var> with Object
 * <var>token</var> that are in the message queue.  If <var>token</var> is null,
 * all callbacks will be removed.
 */
public final void removeCallbacks(Runnable r, Object token)
{
    mQueue.removeMessages(this, r, token);
}

/**
 * Remove any pending posts of messages with code 'what' and whose obj is
 * 'object' that are in the message queue.  If <var>object</var> is null,
 * all messages will be removed.
 */
public final void removeMessages(int what, Object object) {
    mQueue.removeMessages(this, what, object);
}

/**
 * Remove any pending posts of callbacks and sent messages whose
 * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
 * all callbacks and messages will be removed.
 */
public final void removeCallbacksAndMessages(Object token) {
    mQueue.removeCallbacksAndMessages(this, token);
}

MessageQueue.Java fait le vrai travail:

void removeMessages(Handler h, int what, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h && p.what == what
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.what == what
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

void removeMessages(Handler h, Runnable r, Object object) {
    if (h == null || r == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h && p.callback == r
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.callback == r
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

void removeCallbacksAndMessages(Handler h, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h
                && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}
1
JamesRobert