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


当前回答

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

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

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

我的解决方案:

To remove all the callbacks. you need the reference for all the runnables which can be stored in an ArrayList. private ArrayList<Runnable> runnableQueue=new ArrayList<Runnable>(); Then every time u want to post a runnable, store it in the array, then post the array item using 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)); } Then to remove all the callbacks use this method which will remove each callback by iterating through the array. private void removeHandlerCallbacks(){ for(Runnable runnable:runnableQueue){ networkHandler.removeCallbacks(runnable,null); } runnableQueue.clear(); } Hurray! the queue is cleared. But wait. After clearing the array we have to make sure that no more runnable is posted in the handler before you stop the thread. So you have to declare: 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();
}

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

其他回答

请注意,应该在类范围内定义Handler和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()方法调用之前停止它。因为每次都会创建新的Handler和新的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)能够成功工作。

关键的句子是“在你的活动中定义它们为全局的,或者将你使用的内容分割”。

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

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

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

我的解决方案:

To remove all the callbacks. you need the reference for all the runnables which can be stored in an ArrayList. private ArrayList<Runnable> runnableQueue=new ArrayList<Runnable>(); Then every time u want to post a runnable, store it in the array, then post the array item using 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)); } Then to remove all the callbacks use this method which will remove each callback by iterating through the array. private void removeHandlerCallbacks(){ for(Runnable runnable:runnableQueue){ networkHandler.removeCallbacks(runnable,null); } runnableQueue.clear(); } Hurray! the queue is cleared. But wait. After clearing the array we have to make sure that no more runnable is posted in the handler before you stop the thread. So you have to declare: 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();
}

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

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

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

handler.removeCallbacksAndMessages(null);

在removeCallbacksAndMessages的文档中它说…

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

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