如何从Handler中删除所有回调?

时间:2011-05-04 12:48:28

标签: java android callback android-handler

我的子活动中有一个Handler,由主Activity调用。这个Handler被子类用于postDelay一些Runnables,我无法管理它们。现在,在onStop事件中,我需要在完成活动之前删除它们(不知何故我调用finish(),但它仍然一次又一次地调用)。无论如何要从处理程序中删除所有回调吗?

6 个答案:

答案 0 :(得分:477)

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

handler.removeCallbacksAndMessages(null);

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

  

删除任何待处理的回调帖子,并发送obj为令牌的邮件。 如果令牌为null,则系统会删除所有回调和消息。

答案 1 :(得分:18)

对于任何特定的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)删除所有待处理的回调

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

希望有帮助!

答案 2 :(得分:8)

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

答案 3 :(得分:5)

定义一个新的处理程序和runnable:

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

答案 4 :(得分:2)

实际上这里有一点但非常重要的一点。 您应该第一次定义HandlerRunnable。实际上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个实例。这样,您丢失了属于处理程序 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使用的内容中将其定义为全局。。

答案 5 :(得分:1)

正如josh527所说,handler.removeCallbacksAndMessages(null);可以工作。
但是为什么呢?
如果您查看源代码,则可以更清楚地了解它。 可以从处理程序(MessageQueue)中删除回调/消息的方法有3种:

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

Handler.java(保留一些重载方法)

/**
 * 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;
        }
    }
}