Handler.postAtTime与Handler.postDelayed的区别。

6
Android的Handler类包含了这个方法:
public final boolean postAtTime (Runnable r, Object token, long uptimeMillis)

在指定的时间发布一个可运行的任务。稍后可以使用token来从消息队列中移除对r的回调,感谢这个方法:
public final void removeCallbacks (Runnable r, Object token)

在Handler类中不存在以下方法
public final boolean postDelayed (Runnable r, Object token, long delay)

有没有一个很好的理由不提供这样的方法?

你在那里缺少什么?令牌吗? - class stacker
是的,令牌和能够删除使用postDelayed发布的回调函数。 - ben75
你可以随时使用你的Runnable调用Handler.removeCallbacks()。在我看来,它非常有效。 - class stacker
1
这是一个好问题。我发现奇怪的是,文档并没有说明“token”应该是什么,除了作为要移除的Runnables的标识符。 - DeeV
4个回答

5

查看源代码后,令牌对象最终传递到消息中:

public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
308    {
309        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
310    }

private static Message getPostMessage(Runnable r, Object token) {
608        Message m = Message.obtain();
609        m.obj = token;

并且postDelay

 public final boolean postDelayed(Runnable r, long delayMillis)
330    {
331        return sendMessageDelayed(getPostMessage(r), delayMillis);
332    }

如果您想要的是

public final boolean postDelayed (Runnable r, Object token, long delay)

那为什么不直接使用呢?
public final boolean postAtTime (Runnable r, Object token, long uptimeMillis)

因为这是相同的。

更新,忘记添加这个:

public final boolean sendMessageDelayed(Message msg, long delayMillis)
442    {
443        if (delayMillis < 0) {
444            delayMillis = 0;
445        }
446        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
447    }

好的...看起来没有什么好的理由不在API中有postDelayed(Runnable r, Object token, long delay) - ben75
是的,但你可以随时向Android群组提出建议。 - wtsang02
从外观上看,令牌对象似乎是在处理程序类中的一个事后想法,因此该类有些不完整。 - DeeV
1
@ben75 几年后:https://developer.android.com/reference/android/os/Handler#postDelayed(java.lang.Runnable,%20java.lang.Object,%20long) - t0m

2

查看处理程序源代码,似乎存在以下内容:

private final Message getPostMessage(Runnable r, Object token) {
    Message m = Message.obtain();
    m.obj = token;
    m.callback = r;
    return m;
}

可以按照您的需要复制:不用调用postDelayed,而是将您的可运行对象包装在这样一条消息中。

sendMessageDelayed(getPostMessage(r, token), delayMillis);

您可以使用removeCallbacks()函数并将令牌作为参数。

但是它需要你处理消息,这是我很少做的事情,因为这意味着我不能直接使用Handler。 - class stacker
是的,你可以。消息确实会到达Handler.handleMessage,但默认实现是运行Message.callback。如果您查看Handler.post(Runnable)的代码,它以我发布的相同方式创建消息。 - njzk2

1

0

要从处理程序 H 中删除一个 postDelayed runnable r,只需调用 H.removeCallbacks(r)。你为什么需要一个令牌?


据我所知,令牌允许您仅选择一些回调函数以运行(如果可运行对象被多次发布)。 - ben75
好的,我明白了。如果你真的需要使用postDelayed runnable来获取这个token,你可以扩展Handler类以添加一个token属性,并创建自己的postDelayed方法来使用这个token :/ - psykhi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接