Handler.post()源码分析

在分析post源码时候我们先看看Message里面是什么

public final class Message implements Parcelable {
        ****public int what;
        Runnable callback;
        **Message next;**
        Handler target;
        **public long when;**
        Bundle data;
    }

从此看的出Message是一个链表的节点,ok看看post

public final boolean post(@NonNull Runnable r) {
        return sendMessageDelayed(getPostMessage(r), 0);
    }

    public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }

    public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
                                   long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

由此可知,不管是post,还是postdelay实际上调用的都是queue的enqueue,uptimeMillis用的是系统时间 + delay的时间,msg是包装出来的Message,这个我就不读了,现在看看enqueueMessage

boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }

        synchronized (this) {
            if (msg.isInUse()) {
                throw new IllegalStateException(msg + " This message is already in use.");
            }

            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            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;
                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.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

看看这是什么呀

Message p = mMessages; 
**msg.next = p;
mMessages = msg;
典型的链表头插法,mMessage为头结点**
 if (p == null || when == 0 || when < p.when)
 **if (p == null || when < p.when) {
        break;
  }
寻找when时间小于Message.when的节点
大家懂了吧
这就是按照时间降序排序的Message的链表啊**

盲猜Looper取Message时肯定往时间越小的那,拿尾节点实现,按照时间执行handleMessage啊

现在我们看看Looper.loop()是怎么拿东西的

public static void loop() {
        Message msg = queue.next();
        for (;;) {
            ....
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            .....
            msg.target.dispatchMessage(msg);
            .....
            msg.recycleUnchecked();
        }

    }

现在我们去看看queue.next() 看看是不是我说的那样

Message next() {
        ........
        **Message prevMsg = null;
        Message msg = mMessages;**
        if (msg != null && msg.target == null) {
            // Stalled by a barrier.  Find the next asynchronous message in the queue.
            do {
                prevMsg = msg;
                msg = msg.next;
            } **while (msg != null && !msg.isAsynchronous());**
        }
        if (msg != null) {
            if (now < msg.when) {
                // Next message is not ready.  Set a timeout to wake up when it is ready.
                nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
            } else {
                // Got a message.
                mBlocked = false;
                if (prevMsg != null) {
                    prevMsg.next = msg.next;
                } else {
                    mMessages = msg.next;
                }
                msg.next = null;
                if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                msg.markInUse();
                **return msg;**
            }
        } else {
            // No more messages.
            nextPollTimeoutMillis = -1;
        }

        // Process the quit message now that all pending messages have been handled.
        if (mQuitting) {
            dispose();
            return null;
        }
       .......
    }

看到了吧 ,从头开始遍历,一直到取尾巴节点

Handler.post()源码分析

上一篇:Flask(1)- 简介


下一篇:正则表达式匹配