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

Luk*_* Vo 209 java android callback android-handler

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

jos*_*527 492

根据我的经验,这称之为非常好!

handler.removeCallbacksAndMessages(null);
Run Code Online (Sandbox Code Playgroud)

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

删除任何待处理的回调帖子并发送其obj为令牌的邮件.如果是令牌null,则将删除所有回调和消息.

  • 在onDestroy()中使用此命令是否有意义? (3认同)
  • 我有一些问题`removeCallbacksAndMessages(null)`不会删除我的一些回调.当我想要停止接收回调时,我会调用`handler.removeCallbacksAndMessages(null)`并将我的处理程序设置为null,但由于我仍然会得到回调,所以当我想要循环时遇到NPE用`handler.postDelayed()`. (3认同)
  • @Malachiasz我想我会在onStop或onPause中使用它,以确保在活动失去焦点后不处理任何消息.但取决于触发回调/消息时需要做什么 (2认同)
  • @ShrimpCrackers我发现保留可运行实例并使用“yourHandler.removeCallbacks(yourRunnable)”是最可靠的。今天还在用那个。 (2认同)

Dev*_*red 19

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

Handler myHandler = new Handler();
Runnable myRunnable = new Runnable() {
    public void run() {
        //Some interesting task
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

希望有帮助!


alp*_*ero 8

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


ogu*_*han 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();
          }
    } 
Run Code Online (Sandbox Code Playgroud)

如果你调用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();
       }
 } 
Run Code Online (Sandbox Code Playgroud)

这样,您就不会丢失实际引用并removeCallbacks(runnable)成功运行。

关键句子是“在您的ActivityFragment您使用的内容中将它们定义为全局”


sav*_*ion 5

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

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

来电延迟:

handler.postDelayed(runnable, sleep_time);
Run Code Online (Sandbox Code Playgroud)

从处理程序中删除回调:

handler.removeCallbacks(runnable);
Run Code Online (Sandbox Code Playgroud)