Android Handler消息机制详解3

90 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

d.dispatchMessage()

       前面讲到,Looper在loop()时,从MessageQueue中取到消息时,会通过msg.target.dispatchMessage()来通知Handler来进行处理;

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

       可以看到,在该方法内部会进行顺序判断来执行不同的消息处理逻辑:

       1. callback是通过post(Runnable)方式中的Runnable[下面有解释],通过sendMessage时为null;

       2. mCallback默认为null;

       3. 调用子类的handleMessage方法,最终会调用本地实现的Handler中的handleMessage()来进行处理。

3.MessageQueue

       MessageQueue的主要方法有enqueueMessage():将消息添加到queue里;next():不断的取出message;quit():退出消息循环,继而退出Looper.loop()。

a.enqueueMessage()

boolean enqueueMessage(Message msg, long when) {
    ......
    //----------------分析点1------------------------
    synchronized (this) {
        ......
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        //----------------分析点2------------------------
        if (p == null || when == 0 || when < p.when) {
            // New head, wake up the event queue if blocked.
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            // Inserted within the middle of the queue.  Usually we don't have to wake
            // up the event queue unless there is a barrier at the head of the queue
            // and the message is the earliest asynchronous message in the queue.
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            //-------------------分析点3---------------------------
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        //-------------------分析点4---------------------------
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}

      从上面代码可以看到,主要的点为:

      分析点1:加入synchronized (this)是防止多个Handler同时往queue中插入消息,出现混乱的场景。

      分析点2:消息的queue中没有消息或message需要立刻执行(when=0)或当前message执行时间小于queue里面所有消息的最早执行时间时,就把当前message插于queue的头部,然后执行nativeWake()唤醒next(),然后将message最早给loop()执行;

      分析点3:当不满足以上3个条件时,则需要把当前消息根据执行时间(when)插入到queue中的合适位置,此时不需要执行nativeWake()唤醒next(),因为不执行当前消息;

      分析点4:是否需要唤醒next(),来按顺序执行消息;