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

我有一个来自我的子活动的处理程序,它是由主活动活动调用的。这个处理程序被子类用来postDelay一些可运行对象,我不能管理它们。现在,在onStop事件中,我需要在完成活动之前删除它们(我以某种方式调用了finish(),但它仍然一次又一次地调用)。有没有办法从处理程序中删除所有回调?

132698 次浏览

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

不幸的是,你不能简单地“清除”一个Handler的整个MessageQueue,即使你请求与它关联的MessageQueue对象,因为添加和删除项的方法是包保护的(仅在android。OS包可以调用它们)。你可能必须创建一个瘦的Handler子类来管理__abc4列表,因为它们被发布/执行…或者看看在每个Activity之间传递消息的另一个范例

希望有帮助!

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

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

handler.removeCallbacksAndMessages(null);

在removeCallbacksAndMessages的文档中它说…

删除所有obj为token的回调和已发送消息的挂起帖子。如果token为null,则所有回调和消息将被删除。

定义一个新的处理程序和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);

请注意,应该在类范围内定义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实例。这样,你就丢失了属于处理程序可运行的实例的必要引用。

正确方法:

 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)成功工作。

关键句是'在你使用的__ABC0或Fragment中将它们定义为全局'

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

  1. 通过回调(和令牌)删除
  2. 通过留言删除。什么(和标志)
  3. 通过令牌删除

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

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

删除特定的可运行对象

handler.removeCallbacks(yourRunnable)

删除所有可运行程序

handler.removeCallbacksAndMessages(null)

没有一个解决方案对我有效。但我找到了一个有效的解决办法。

已经添加到处理程序队列中的可运行对象即使在调用handler.removeCallbacksAndMessages(null)之后也会被执行。当我试图停止线程时,它导致了错误:

W/MessageQueue(6436): java.lang.RuntimeException: Handler (android.os.Handler) {416659f0} 发送消息到死线程上的Handler . runtimeexception: Handler (android.os.Handler) {416659f0

我的解决方案:

  • 删除所有回调。你需要所有的参考

    .可运行对象,可存储在数组列表中
     private ArrayList<Runnable> runnableQueue=new ArrayList<Runnable>();
    
  • 然后每次你想要发布一个可运行对象时,将它存储在数组中,然后使用handler.post()发布数组项。

    private void postInHandler(){
    @override
    runnableQueue.add(new Runnable() {
    public void run() {
    //your code
    }
    });
    //Post the last item in the array
    handler.post(runnableQueue.get(runnableQueue.size()-1));
    }
    
  • 然后使用此方法删除所有回调,该方法将通过遍历数组删除每个回调。

      private void removeHandlerCallbacks(){
    for(Runnable runnable:runnableQueue){
    networkHandler.removeCallbacks(runnable,null);
    }
    runnableQueue.clear();
    }
    
  • < p >华友世纪!清除队列。但是等等。在清除数组后,我们必须在停止线程之前确保处理程序中的没有更多的runnable被张贴。所以你必须声明:

    boolean allowPosting=true;

所以要包括这些:

private void removeHandlerCallbacks(){
allowPosting=false;//add this line to stop posting after clearing the array
for(Runnable runnable:runnableQueue){
handler.removeCallbacks(runnable,null);
}
//Dont forget to clear the array
runnableQueue.clear();
}

然后在提交到处理程序之前检查条件:

if(allowPosting){
postInHandler();
}

这就是全部,现在队列被清除,我们确定在清除队列后没有更多的可运行对象被发布。所以停止线程是安全的。