247

我的子 Activity 有一个Handler,它由主Activity调用。这个 Handler 被postDelay一些 Runnables 的子类使用,我无法管理它们。现在,在这种情况onStop下,我需要在完成 Activity 之前删除它们(我以某种方式调用finish()了 ,但它仍然一次又一次地调用)。无论如何要从处理程序中删除所有回调?

4

6 回答 6

565

根据我的经验,这很有效!

handler.removeCallbacksAndMessages(null);

在 removeCallbacksAndMessages 的文档中,它说...

删除所有待处理的回调和发送的消息,其 obj 是令牌。如果 token 是null,所有回调和消息都将被删除。

于 2012-04-13T17:38:14.417 回答
20

对于任何特定Runnable实例,请调用Handler.removeCallbacks(). 请注意,它使用Runnable实例本身来确定要取消注册的回调,因此如果您在每次发布帖子时都创建一个新实例,则需要确保您引用了Runnable要取消的确切引用。例子:

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

您可以调用myHandler.postDelayed(myRunnable, x)以将另一个回调发布到代码中其他位置的消息队列,并删除所有待处理的回调myHandler.removeCallbacks(myRunnable)

不幸的是,您不能简单地“清除”整个MessageQueuea Handler,即使您请求MessageQueue与其关联的对象也是如此,因为添加和删除项目的方法是包保护的(只有 android.os 包中的类可以调用它们)。您可能必须创建一个瘦子Handler类来管理Runnable发布/执行的 s 列表......或者查看另一种范式以在每个 s 之间传递消息Activity

希望有帮助!

于 2011-05-04T12:58:07.013 回答
8

如果您没有 Runnable 引用,则在第一个回调中,获取消息的 obj,并使用removeCallbacksAndMessages()删除所有相关回调。

于 2011-05-04T13:17:05.783 回答
8

定义一个新的处理程序并运行:

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

来电发帖延迟:

handler.postDelayed(runnable, sleep_time);

从您的处理程序中删除您的回调:

handler.removeCallbacks(runnable);
于 2015-01-20T14:42:27.933 回答
7

请注意,应该在类范围内定义 aHandler和 a Runnable,以便创建一次。removeCallbacks(Runnable)除非多次定义它们,否则它们可以正常工作。请查看以下示例以更好地理解:

不正确的方式:

    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();
          }
    } 

如果你调用onClick(..)方法,你永远不会在调用之前停止doIt()方法调用。因为每次都会创建new Handlernew Runnable实例化。通过这种方式,您丢失了属于处理程序可运行实例的必要引用。

正确方法:

 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();
       }
 } 

这样,您就不会丢失实际的参考资料并且removeCallbacks(runnable)可以成功工作。

关键句是“将它们定义为您您使用的全局ActivityFragment” 。

于 2016-12-14T19:48:03.657 回答
2

如前所述josh527handler.removeCallbacksAndMessages(null);可以工作。
但为什么?
如果你看一下源代码,你可以更清楚地理解它。有 3 种方法可以从处理程序(消息队列)中删除回调/消息:

  1. 通过回调(和令牌)删除
  2. 通过 message.what (和令牌)删除
  3. 令牌删除

Handler.java(留一些重载方法)</p>

/**
 * 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 做真正的工作:

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;
        }
    }
}
于 2018-11-29T02:46:46.293 回答