如何从 postDelayed 添加的处理程序对象中删除可运行对象?

Posted

技术标签:

【中文标题】如何从 postDelayed 添加的处理程序对象中删除可运行对象?【英文标题】:How to remove a runnable from a handler object added by postDelayed? 【发布时间】:2011-04-07 08:00:09 【问题描述】:

我有一个“打开” 动画,我正在使用Handler.postDelayed(Runnable, delay) 在短暂延迟后触发一个“关闭” 动画。但是,在打开和关闭之间的这段时间内,可能还有另一个由点击触发的动画。

我的问题是,如何取消处理程序中的 "close" 动画?

【问题讨论】:

如果您使用 Kotlin,请注意这个答案:***.com/a/30905295/2736039,我试过了,但遇到了这个问题(仅在 Kotlin 中):***.com/questions/62405834/… 【参考方案1】:

只需使用removeCallbacks(Runnable r) 方法即可。

【讨论】:

是否可以删除匿名可运行对象的回调? 我不这么认为......你将不得不使用非匿名的。否则您以后将无法引用它们。 查看@NameSpace 的回答。如果您使用令牌发布可运行文件,则可以删除待处理的可运行文件。或者您可以使用 Daniel L. 的方法,使用 null 令牌删除所有回调/消息。 在 removeCallbacks(Runnable r) 不可用的情况下删除 API 的特定回调有什么建议吗? 这会删除所有出现的实例吗?因为我以不同的延迟时间多次发布它【参考方案2】:

克里斯蒂安的回答是正确的,但与答案的 cmets 中所述相反,您实际上可以通过调用 removeCallbacksAndMessages(null); 来删除匿名 Runnables 的回调

如here所述:

删除所有待处理的回调和已发送消息,其 obj 为令牌。 如果 token 为空,所有的回调和消息都会被移除

【讨论】:

我只想指出,无论您处理的是Handler 还是View 类,这种行为都是不同的。在View 类中(可能在4.0 之后?),您必须使用相同的Runnable 对象来取消任务,而对于Handler 类,如果您通过null,它们将全部被取消。尽管如此,问题指定了Handler,因此您的答案是正确的。 真的!!谢谢..那里有一些可运行的,而removeCallbacks什么也没做!!!!!!!但这确实有效:) thx【参考方案3】:

这是一个较晚的答案,但是当您只想从处理程序中删除特定类别的可运行文件时,这是一种不同的方法(即在 OP 的情况下,只需删除关闭动画,将其他可运行文件留在队列中):

    int firstToken = 5;
    int secondToken = 6;

    //r1 to r4 are all different instances or implementations of Runnable.  
    mHandler.postAtTime(r1, firstToken, 0);
    mHandler.postAtTime(r2, firstToken, 0);
    mHandler.postAtTime(r3, secondToken, 0);

    mHandler.removeCallbacksAndMessages(firstToken);

    mHandler.postAtTime(r4, firstToken, 0);

上面的代码将只执行“r3”,然后只执行“r4”。这使您可以删除由令牌定义的特定类别的可运行文件,而无需保存对可运行文件本身的任何引用。

注意:源代码仅使用“==”操作数比较标记(它不调用 .equals()),因此最好使用整数/整数而不是字符串作为标记。

【讨论】:

我看到了你的答案,我从string 更改为int 然后我有一天这个错误:D ***.com/q/62405834/2736039 这在 Kotlin 中对于 int > 127 不起作用,只是将此评论留在这里作为对未来读者的提示【参考方案4】:

如果你使用递归,你可以通过传递“this”来实现。请参阅下面的代码。

public void countDown(final int c)
    mHandler.postDelayed(new Runnable() 
        @Override
        public void run() 
            aq.id(R.id.timer).text((c-1)+"");
            if(c <= 1)
                aq.id(R.id.timer).gone();
                mHandler.removeCallbacks(this);
            else
                countDown(c-1);
            
        
    , 1000);

此示例将设置 TextView(计时器)的文本每秒,倒计时。一旦它变为 0,它将从 UI 中删除 TextView 并禁用倒计时。这仅对使用递归的人有用,但我到这里是为了寻找它,所以我发布了我的结果。

【讨论】:

以上是关于如何从 postDelayed 添加的处理程序对象中删除可运行对象?的主要内容,如果未能解决你的问题,请参考以下文章

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

Android postdelayed处理程序无法启动运行

Android Studio - 如何从片段中停止 handler.postDelayed?

android postDelayed实现

AsyncTask - 如何在AsyncTask中使用带有postDelayed(Runnable,int)的Handler?

如何在处理程序中将 java 转换为 kotlin