Handler.removeCallbacks(Runnable r)失效原因

今天发现一个问题就是Android中使用Handle的removeCallbacks函数将Runnable移除,可是有时候会失效,在网上搜索了很久,大部分都是解决方法,依然没有说明为什么失效的原因。

在StackOverFlow找到一点原因:

It appears to me that removeCallbacks(..) only stops pending messages (Runnables). If your runnable has already started, then there's no stopping it (at least not this way).

removeCallbacks只能停止处于即将运行状态的messages,这里messages里面包含就是Runnables,如果Runnbale已经启动start(),则removeCallbacks是无法停止的。

感觉很厉害的人都是自己找问题答案的,所以今天我也要学学他们,自己找答案。

在Handler的removeCallbacks()方法是调用:

 public final void removeCallbacks(Runnable r)
{
   mQueue.removeMessages(this, r, null);
}

mQueue就是MessageQueue,接着看removeMessages方法

 void removeMessages(Handler h, Runnable r, Object object) {
       if (h == null || r == null) {
            return;
       }

       synchronized (this) {
           Message p = mMessages;
      // Remove all messages at front. 
      // 就是将当前处于mMessage前面的message(里面有目标callback)移除
           while (p != null && p.target == h && p.callback == r
                 && (object == null || p.obj == object)) {
                 Message n = p.next;
                mMessages = n;
                p.recycleUnchecked();//将移除的message放入pool中
                p = n;
            }

     // Remove all messages after front.
     // 就是将当前处于后面的message(里面有目标callback)移除      
           while (p != null) {
                Message n = p.next;
                if (n != null) {
                    if (n.target == h && n.callback == r
                        && (object == null || n.obj == object)){
                        Message nn = n.next;
                        n.recycleUnchecked();
                        p.next = nn;
                        continue;
                    }
                }
                p = n;
            }
        }
    }

可见mQueue.removeMessages(this, r, null);是将messageQueue中的包含有我们想要移除的callback的message全部移除掉,这样不就达到阻止runnable运行的目的了吗?

但是假如我们想要移除的callback不在messageQueue中,那么mQueue.removeMessages也就失效了。

因为已经处于运行的runnable包含在message中已经移交给handler进行处理了,而Handler.removeCallbacks(Runnable r)只能移除未运行的runnable,所以导致无法停止runnbale的运行,最后失效。

你可能感兴趣的:(Handler.removeCallbacks(Runnable r)失效原因)