handler.removeCallbacks(null)不能清除Runnable问题

  我们知道调用handler.removeCallbacksAndMessages(null);可以清空当前handler的所有回调和所有消息。想当然的认为handler.removeCallbacks(null)可以清空所有回调,实则不然。本文旨在探明其原因。
  首先,打开Handler.java,removeCallbacksAndMessages方法如下:

    /**
     * Remove any pending posts of callbacks and sent messages whose
     * obj is token.  If token is null,
     * all callbacks and messages will be removed.
     */
    public final void removeCallbacksAndMessages(Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }

  可以看到,注释中有提到参数为null时会移除所有回调和message,再看removeCallbacks方法,注释中并没有提到参数为null时会移除所有回调。

    /**
     * Remove any pending posts of Runnable r that are in the message queue.
     */
    public final void removeCallbacks(Runnable r)
    {
        mQueue.removeMessages(this, r, null);
    }

  如果还不确信的话,我们可以继续向下探究。上文可以看到无论是在removeCallbacksAndMessages方法还是removeCallbacks方法中都继续调用了mQueue对象中的removeCallbacksAndMessages和removeMessages方法,mQueue对象是MessageQueue类的实例,打开MessageQueue.java文件找到这两个方法。首先是removeCallbacksAndMessages:

    void removeCallbacksAndMessages(Handler h, Object object) {
        if (h == null) {
            return;
        }

        synchronized (this) {
            Message p = mMessages;

            // Remove all messages at front.
            while (p != null && p.target == h
                    && (object == null || p.obj == object)) {
                Message n = p.next;
                mMessages = n;
                p.recycleUnchecked();
                p = n;
            }

            // Remove all messages after front.
            while (p != null) {
                Message n = p.next;
                if (n != null) {
                    if (n.target == h && (object == null || n.obj == object)) {
                        Message nn = n.next;
                        n.recycleUnchecked();
                        p.next = nn;
                        continue;
                    }
                }
                p = n;
            }
        }
    }

  从该方法可以看出,当传入的object对象为null时,会循环回收掉所有message。在看removeMessages方法,当传入的Runnable为null时,会直接退出,该方法如下:

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

        synchronized (this) {
            Message p = mMessages;

            // Remove all messages at front.
            while (p != null && p.target == h && p.callback == r
                   && (object == null || p.obj == object)) {
                Message n = p.next;
                mMessages = n;
                p.recycleUnchecked();
                p = n;
            }

            // Remove all messages after front.
            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;
            }
        }
    }

  所以handler.removeCallbacks(null)不会移除任何回调。

你可能感兴趣的:(handler.removeCallbacks(null)不能清除Runnable问题)