如何从处理程序中删除所有回调?


222

我有一个来自主Activity调用的子Activity中的Handler。该处理程序由某些Runnable 的子类使用,但我无法对其进行管理。现在,在这种情况下,我需要先删除它们,然后再完成“活动”(以某种方式调用,但仍会反复调用)。无论如何,要从处理程序中删除所有回调吗?postDelayonStopfinish()

Answers:


521

根据我的经验,这非常有效!

handler.removeCallbacksAndMessages(null);

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

删除obj为令牌的回调和已发送消息的所有未决帖子。如果token是null,则将删除所有回调和消息。


2
@Malachiasz我想我会在onStop或onPause中使用它,以确保在活动失去焦点后不会处理任何消息。但是取决于触发回调/消息时需要执行的操作
Boy

1
我相信这样做之前我曾经在某些电话上见过NPE,但是已经有一段时间了。
马特·沃尔夫,2015年

3
我遇到了一些问题,removeCallbacksAndMessages(null)无法删除某些回调。当我想停止接收回调时,我会调用handler.removeCallbacksAndMessages(null)并将我的处理程序设置为null,但是由于我仍然会收到回调,因此当我想与循环时会遇到NPE handler.postDelayed()
Snaker

@Snaker您解决问题了吗?我有一个同样的问题,即使通过设置null删除回调和消息后,也要调用Handler.Callback。
ShrimpCrackers

1
@ShrimpCrackers我发现保留可运行实例并使用yourHandler.removeCallbacks(yourRunnable)是最可靠的。今天仍在使用。
Snaker

19

对于任何特定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)

不幸的是,你不能简单地“清除”了整个MessageQueueHandler,即使你做了要求MessageQueue它,因为添加和删除项目的方法有包保护(只android.os包中的类可以给他们打电话)相关联的对象。您可能必须创建一个瘦子Handler类来管理Runnables 的列表,这些列表在发布/执行时……或查看另一种在每个s之间传递消息的范式Activity

希望对您有所帮助!


谢谢,我知道。但是我在许多子类中都有很多Runnable,并且管理它们都是史诗般的工作!无论如何,在onStop()事件中是否将其全部删除?
路加福音

可以理解,我用更多信息更新了答案。简短的版本是您不能调用一种方法来广泛清除Handler的消息队列…
Devunwired 2011年


6

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

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

3

请注意,应该定义一个Handler和一个Runnablein类范围,以便一次创建它。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你用什么”


1

如前所述josh527handler.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;
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.