欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

从源码角度简单分析下Handler发消息流程

程序员文章站 2022-06-03 23:39:10
一、发送消息(sendMssage)handler.sendMessage(message)handler.sendMessageDelayed()等发送消息的方法,最终都会走到sendMessageAtTime public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { R...
一、发送消息(sendMssage)

handler.sendMessage(message)
handler.sendMessageDelayed()等发送消息的方法,最终都会走到sendMessageAtTime

 public boolean sendMessageAtTime(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);
    }
二、将Mssage存入队列
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;//这里记录下msg.target就是Handler自己
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

在sendMessageAtTime中将msg放到了队列,这个队列是链表形式的队列,而且需要以时间排序

三,从MessageQueue中取出Message

然后我们再看看MessageQueue的next方法

 Message next() {
       ...
        for (;;) {
            ...

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                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;//这里先在do while中取消息
                    } 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;
                }

               .....
        }
    }

1.这里先在do while中取消息
2.然后用当前时间对比,看发送时间有没有到
3.如果到了发送时间,直接返回消息

然后看看下Looper的loop()方法,

  
    public static void loop() {
        final Looper me = myLooper();
       ...
        final MessageQueue queue = me.mQueue;

      ...
        for (;;) {//这里有个死循环,从MessageQueue 中取Message 
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

          
           ...

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            try {
                msg.target.dispatchMessage(msg);//然后进行消息分发
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            
            ...

            msg.recycleUnchecked();
        }
    }

loop()里面主要做了两件事
1.在一个死循环里面,从从MessageQueue 中取Message
2.调用msg.target.dispatchMessage(msg)将Message分发出去

四,将取出Message的进行分发

在上面Handler的enqueueMessage源码里面可以看出这个target就是Handler,所以我们再跟一下Handler的dispatchMessage方法

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {//这里的callback就是用Handler的post方法发送的Runnable 对象,待会看源码
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);//在这里调用Handler的handleMessage方法
    }

这里补下Handler的post相关源码

public final boolean post(Runnable r){
   return  sendMessageDelayed(getPostMessage(r), 0);
}
    
  private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;//在这里给callback 赋值
        return m;
    }
 public final boolean sendMessageDelayed(Message msg, long delayMillis){
     if (delayMillis < 0) {
          delayMillis = 0;
     }
     return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//这里还是通过sendMessageAtTime将消息发送给了队列
}

本文地址:https://blog.csdn.net/zzq2006/article/details/109632748