前言

Message 机制作为一种系统通信机制,主要涉及到了以下几个部分(java 层):

  • Handler.java
  • Looper.java
  • Message.java
  • MessageQueue.java

其被广泛应用于系统和应用的各处,例如:

Message msg = mWorkerHandler.obtainMessage(MSG_HANDLE_PKG_EVENT, event);
        mWorkerHandler.sendMessage(msg);

下面我们就来看一看它是怎样实现通信的,以及其究竟干了什么。

一、Message 的添加

1.1 obtainMessage

1.1.1 Handler.obtainMessage

Handler.java

public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }

1.1.2 Message.obtain

Message.java

public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }

由此可知,obtainMessage 的作用是:

  • 调用 Message 的 obtain() 方法得到一个 Message 对象
  • 对 Message 对象的各个成员变量进行赋值,其中 target 即被赋值为调用 obtainMessage 的 Handler 对象,即 mWorkerHandler

1.1.3 Message.obtain()

Message.java

public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

从上面看来,obtain() 会检查 sPool 这个 Message Pool 是否为空,如果不为空则从头部取出一个 Message 对象,如果为空则返回一个新构建的 Message 对象;
下面再来考虑一个问题:此处的 sPool 是什么?

1.1.4 Message.sPool

Message.java

private static Message sPool;
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 50;

    /* 回收 Message */
    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                ...
            }
            return;
        }
        recycleUnchecked();
    }

    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                // 把 this 插入到 sPool 中
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

由此可见:

  • sPool 是由我们之前创建后回收的 Message 对象填充起来的
  • FLAG_IN_USE 这个 FLAG 在被 recycle 和 enqueueMessage 时都会被标记;并且在被 recycle 时,Message 对象其他信息会被清空

sendMessage

1.2.1 Handler.sendMessage

Handler.java

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

1.2.2 sendMessageDelayed

Handler.java

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

把 delayMillis 转化为 SystemClock 时间

1.2.3 sendMessageAtTime

Handler.java

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);
    }

这里我们先留一个疑问: mQueue 是什么?

1.2.4 enqueueMessage

Handler.java

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        // 这里又会对 msg.target 附一次值
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        // 调用 MessageQueue 的 enqueueMessage 方法
        return queue.enqueueMessage(msg, uptimeMillis);
    }

1.3 enqueueMessage

1.3.1 MessageQueue.enqueueMessage

MessageQueue.java

boolean enqueueMessage(Message msg, long when) {
        ...
        synchronized (this) {
            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;
    }

这里主要是按照插入 mMessages 头部和插入 mMessages 中两种情况将传过来的 Message 对象插入 mMessages 队列中
下面我们来看一下 mMessages 队列中的 Message 是怎么被处理的。

二、Message 的分发

以开头的程序示例为例,我们来看一下 mWorkerHandler 是怎么初始化的:

mHandlerThread = new HandlerThread("String ...", Process.THREAD_PRIORITY_BACKGROUND);
// 会启动一个新线程,并在新线程中运行run()方法
mHandlerThread.start();
mWorkerHandler = new EventWorkHandler(mHandlerThread.getLooper());

public class HandlerThread extends Thread {
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
}

2.1 Looper

2.1.1 Looper.prepare()

Looper.java

public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

由此可知,mQueue 指向 Looper 对象自己的 MessageQueue,mThread 指向 Looper 对象所在的线程

2.1.2 Looper.loop()

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        ...
        for (;;) {
            // 取出下一个需要处理的 Message,涉及到 native 层,暂不讨论
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // 调用目标 Handler 的 dispatchMessage 方法
            msg.target.dispatchMessage(msg);
            msg.recycleUnchecked();
        }
    }

可以看出 loop() 方法就是不断地循环,对其 MessageQueue 中的 Message 进行处理。

2.2 Handler

2.2.1 Handler 的初始化

我们再来看一下 1.2.3 中所留的疑问:mQueue 是什么?

public Handler(Looper looper) {
        this(looper, null, false);
    }

    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

由此可知:Handler 中 mQueue 所指的队列其实就是 Looper 初始化时为自己创建的 MessageQueue

2.2.2 Handler.dispatchMessage

Handler.java

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

由此可以看出,dispatchMessage 做了如下事情:

  • 如果 Message 有 callback,则执行 callback 的 run() 方法
  • 如果 Message 没有 callback
  • 如果 Handler 有 mCallback,执行 mCallback 的 handleMessage() 方法
  • 执行 Handler 的 handleMessage 方法

总结

3.1 各组件结构图

Java存储msg文件 java中msg是什么意思_赋值

上图列出了 Message 机制涉及到的主要的类以及他们之间的关系:

  • Looper 内部有 mQueue 和 mThread 两个成员,分别指向其构建的 MessageQueue 和其所在的 Thread
  • MessageQueue 中保存了一个 Messages 组成的队列 mMessages
  • Message 中的 target 指向用 Looper 构建的 Handler
  • Handler 中的 mLooper 和 mQueue 分别指向初始化时传过来的 Looper 以及 Looper 中的 mQueue

因此,Message 的处理(handleMessage 等)是在 Handler 的 Looper 所在的线程中完成的

3.2 Message 机制的工作

  • Looper 一直在循环,从其 mQueue 中取出 Message 并调用目标 Handler 的 dispatchMessage 方法(Message 的分发)
  • 构建 Message,并通过 sendMessage 等方法将其添加到 MessageQueue 中(Message 的添加)

3.3 Message 的创建

Message 主要包含以下内容:

数据类型

成员变量

含义

int

what

消息代号

long

when

消息触发时间

int

arg1

参数1

int

arg2

参数2

Object

obj

消息内容对象

Handler

target

目标 Handler

Runnable

callback

回调方法

创建 Message 的过程,就是填充 Message 的上述内容的一项或多项的过程