笔友城堡 - 可定义的个人主页

前言

在使用Handler时,当Activity销毁时,经常使用

mHandler.removeCallbacksAndMessages(null);

虽然经常用,但大多数人都没深入了解一下。

这里简单记录一下,方便自己查询。

正文

这里主要涉及Handler 和MessageQueue

Handler.java

\frameworks\base\core\java\android\os\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(@Nullable Object token) {
    mQueue.removeCallbacksAndMessages(this, disallowNullArgumentIfShared(token));
}

调用的是MessageQueue对象。

MessageQueue.java

\frameworks\base\core\java\android\os\MessageQueue.java
//传入的object为null
void removeCallbacksAndEqualMessages(Handler h, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;
        // Remove all messages at front.
        //因为object为null,如果target==h,那么就会进入循环中。
        //如果target不为h的消息,那就跳过,进入下面
        //【while 一】
        while (p != null && p.target == h
                && (object == null || object.equals(p.obj))) {
            //进入这里的就是h的消息,因为我们要退出了
            //因此要移除所有h的消息
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();//回收
            p = n;
        }

        // Remove all messages after front.
        //p不为null,根据上面p肯定不是h的消息
        //那就看p后面的消息是不是h的,然后一直遍历所有的。
        //【while二】
        while (p != null) {
            Message n = p.next;
            //下一个消息不为null时
            if (n != null) {
                //判断是否是h的消息,如果是,那就需要移除。
                if (n.target == h && (object == null || object.equals(n.obj))) {
                    Message nn = n.next;
                    n.recycleUnchecked();//回收
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

下面简单举例分析一下removeCallbacksAndEqualMessages()中的移除流程。

知识拓展

要知道Message、Looper、Handler、MessageQueue、以及Thread的对应关系。

关系对应
Thread持有 1 个 Looper
Looper持有 1 个 MessageQueue
Handler绑定 1 个 Looper(多个 Handler 可以共用同一个 Looper)
Message绑定 1 个 Handler(target)
MessageQueue持有 N 个 Message

多个 Handler 可以共用同一个 Looper

例子1

 //是h的消息下面有↑h
 messages → A  →  B  →  C  →  D  →  E  →  F
                  ↑h          ↑h   ↑h    

上面看做消息队列里面有A、B、C、D、E、F等消息。

假设消息A不是h分发的消息,那么就不满足代码中【while一】,p = message A,然后进入【while二】然后遍历后面的所有消息。

注意,后面的消息也不一定是h的,但是【while二】中做了全部的遍历,只有满足才会进入回收。

例子2

 messages → A  →  B  →  C  →  D  →  E  →  F
            ↑h    ↑h          ↑h    

当然,A和B都是h的消息,满足【while一】的条件,但是C不是,退出【while一】的循环,然后p=message C,然后进入【while二】的遍历循环。

参考文章

  1. AI

  2. Android源码

相关文章

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...