程序笔记   发布时间:2022-07-18  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了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.recycleUn@R_197_10943@ked();
        }

    }

现在我们去看看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()源码分析全部内容,希望文章能够帮你解决Handler.post()源码分析所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。