【从源码看Android】03Android MessageQueue消息循环处理机制(e

1 enqueueMessage

handler发送一条消息

mHandler.sendEmptyMessage(1);经过层层调用,进入到sendMessageAtTime函数块,最后调用到enqueueMessage

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

最后调用到Handler私有的函数enqueueMessage,把handler对象赋值给msg.target,调用queue.enqueueMessage

Handler.javaprivate boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

下面是核心代码,首先是获得同步锁,

MessageQueue.java

boolean enqueueMessage(Message msg, long when) {if (msg.isInUse()) {throw new AndroidRuntimeException(msg + " This message is already in use.");}if (msg.target == null) {throw new AndroidRuntimeException("Message must have a target.");}synchronized (this) {if (mQuitting) {RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");Log.w("MessageQueue", e.getMessage(), e);return false;}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.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;}首先是获得自身的同步锁synchronized (this),接着这个msg跟MessageQueue实例的头结点Message进行触发时间先后的比较,

如果触发时间比现有的头结点Message前,则这个新的Message作为整个MessageQueue的头结点,如果阻塞着,则立即唤醒线程处理

如果触发时间比头结点晚,则按照触发时间先后,在消息队列中间插入这个结点

接着如果需要唤醒,则调用nativeWake函数

在android_os_MessageQueue.cpp里定义了nativeWake函数

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);return nativeMessageQueue->wake();}实际调用到mLooper->wake();

android_os_MessageQueue.cpp

void NativeMessageQueue::wake() {mLooper->wake();}而mLooper是cpp层的Looper对象,

framework/base/libs/utils/Looper.cpp

void Looper::wake() {#if DEBUG_POLL_AND_WAKELOGD("%p ~ wake", this);#endif#ifdef LOOPER_STATISTICS// FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.if (mPendingWakeCount++ == 0) {mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);}#endifssize_t nWrite;do {nWrite = write(mWakeWritePipeFd, "W", 1);} while (nWrite == -1 && errno == EINTR);if (nWrite != 1) {if (errno != EAGAIN) {LOGW("Could not write wake signal, errno=%d", errno);}}}是不是很熟悉?基本就是上一讲epoll原型的唤醒函数,向mWakeWritePipeFD写入1字节,唤醒监听block在mWakeReadPipeFD端口的epoll_wait

2 dequeueMessage

首先dequeueMessage只是我取的一个叫法,当java层的Looper进行loop的时候,就已经在不停地读取MessageQueue里的Message了

Looper.java

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;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerPrinter logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}msg.target.dispatchMessage(msg);if (logging != null) {logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasn't corrupted.final long newIdent = Binder.clearCallingIdentity();if (ident != newIdent) {Log.wtf(TAG, "Thread identity changed from 0x"+ Long.toHexString(ident) + " to 0x"+ Long.toHexString(newIdent) + " while dispatching to "+ msg.target.getClass().getName() + " "+ msg.callback + " what=" + msg.what);}msg.recycle();}}调用queue.next()读取下一条消息(在loop调用的线程中),如果读取到了就msg,target.dispatchMessage,

下面来看看queue.next()如何实现

风景如何,其实并不重要。重要的是,你在我的身边。

【从源码看Android】03Android MessageQueue消息循环处理机制(e

相关文章:

你感兴趣的文章:

标签云: