为什么发布&取消了View和Handler上的runnable导致不同的bahviour?

时间:2012-03-19 10:40:10

标签: android view handler runnable

我一直在玩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}}

3 个答案:

答案 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