我一直在玩Runnable
,并且发现如果postDelayed
Runnable
View
Runnable
,那么删除回调将无效如果您执行相同的操作,但在Handler
上发布Runnable
,则删除回调确实有效。
为什么这样做(Runnable runnable = new Runnable() {
@Override
public void run() {
// execute some code
}
};
Handler handler = new Handler();
handler.postDelayed(runnable, 10000);
handler.removeCallbacks(runnable);
run()代码永远不会被执行):
Runnable
这里没有(Runnable runnable = new Runnable() {
@Override
public void run() {
// execute some code
}
};
View view = findViewById(R.id.some_view);
view.postDelayed(runnable, 10000);
view.removeCallbacks(runnable);
run()代码总是被执行)?:
{{1}}
答案 0 :(得分:4)
如果View
没有附加到窗口,我可以看到这种情况发生,这可以说是Android中的错误。因此,从战术上讲,这可能是一个时间问题,确保在Runnable
附加到窗口之前不会发布或删除View
。
如果您碰巧有一个示例项目,那就复制了这个问题,我想看看它。否则,我会尝试制作自己的,所以我可以用一些东西来报告我假定的错误。
<强>更新强>
正如评论中所提到的,removeCallbacks()
对更多普通小部件起作用,因此根据OP的示例代码,这似乎是WebView
特定的问题。
答案 1 :(得分:0)
由于各种原因,当您要启动动画时,View的处理程序(view.getHandler())可能尚未就绪。
因此,您应该在将runnable分配给视图之前等待。
假设您正在尝试从Activity中执行此操作,这里是一个代码,在发布runnable之前等待处理程序可用:
private void assignRunnable(final View view, final Runnable runnable, final int delay)
{
if (view.getHandler() == null) {
// View is not ready, postpone assignment
this.getView().postDelayed(new Runnable() {
@Override
public void run() {
assignRunnable(view, runnable, delay);
}
}, 100);
//Abort
return;
}
//View is ready, assign the runnable
view.postDelayed(runnable, delay);
}
答案 2 :(得分:0)
查看ViewRootImpl.java,View.removeCallbacks()的语义似乎至少可以说不清楚。
RunQueue.removeCallbacks
只是从ArrayList中删除了Runnables。请参阅here。
如果在removeCallbacks之前调用RunQueue.executeActions
,那么在所有情况下都会清除ArrayList,使removeCallbacks
成为无操作。请参阅here。
RunQueue.executeActions
....请参阅here。
因此,除非我遗漏某些内容,否则如果您在致电View.removeCallbacks
后发生了遍历,则View.post
将无效。
我会坚持上面的@ james-wald评论而不是View.post