thread { Log.d("MainActivity","thread is ${Thread.currentThread().name}") val handler = MyHandler(Looper.getMainLooper())
val message = Message().apply { what = 1 obj = "message" } handler.sendMessage(message)
}
日志如下:
可见已经切换到主线程中接收到信息了
1 2
MainActivity: thread is Thread[main,5,main] MyHandler: thread is main msg.what is 1
通过以上的例子,我们来分析 Android 中的消息机制到底是如何运作的
2. Looper
2.1 prepare()
将当前线程初始化为循环线程
1 2 3 4 5 6
privatestaticvoidprepare(boolean quitAllowed){ if (sThreadLocal.get() != null) { thrownew RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
可见,第一次调用 prepare() 方法时会在当前线程中 new 一个 Looper 对象,并保存在该线程的 mThreadLocal 中
publicstaticvoidloop(){ final Looper me = myLooper(); if (me == null) { //Looper 还没有初始化,则抛出异常 thrownew RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } if (me.mInLoop) { Slog.w(TAG, "Loop again would have the queued messages be executed" + " before this one completed."); }
me.mInLoop = true; 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(); finallong ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g. // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start' finalint thresholdOverride = SystemProperties.getInt("log.looper." + Process.myUid() + "." + Thread.currentThread().getName() + ".slow", 0);
boolean slowDeliveryDetected = false;
for (;;) { //开始进入死循环 //获取消息队列中的第一条消息,可能回阻塞 Message msg = queue.next(); // might block if (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 logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } // Make sure the observer won't change while processing a transaction. final Observer observer = sObserver;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); }
finallong dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0; finallong dispatchEnd; Object token = null; if (observer != null) { token = observer.messageDispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid); try { //消息不为空,分发给消息对应的 target(即 Handler)去处理 msg.target.dispatchMessage(msg); if (observer != null) { observer.messageDispatched(token, msg); } dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) { if (observer != null) { observer.dispatchingThrewException(token, msg, exception); } throw exception; } finally { ThreadLocalWorkSource.restore(origWorkSource); if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logSlowDelivery) { if (slowDeliveryDetected) { if ((dispatchStart - msg.when) <= 10) { Slog.w(TAG, "Drained"); slowDeliveryDetected = false; } } else { if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery", msg)) { // Once we write a slow delivery log, suppress until the queue drains. slowDeliveryDetected = true; } } } if (logSlowDispatch) { showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", 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. finallong 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.recycleUnchecked(); } }
obtain() 方法判断当 sPool 不为空时,即已经有被创建出来的 Message 对象了,则赋值给 m 并将 m.next 赋值给 sPool,即将单链表中的第一个节点取出,并将第二个节点作为 sPool ,即剩下的链表继续作为缓存池,同时将缓存池的数量减一。最后将需要返回的 m 的 next 赋值为 null,清除 flag 等并返回 m
3.2 recycler()
1 2 3 4 5 6 7 8 9 10
publicvoidrecycle(){ if (isInUse()) { if (gCheckRecycle) { thrownew IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); }
voidrecycleUnchecked(){ // 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 = UID_NONE; workSourceUid = UID_NONE; when = 0; target = null; callback = null; data = null;
synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
4.3 sendMessageAtTime(Message msg, long uptimeMillis)
1 2 3 4 5 6 7 8 9 10
publicbooleansendMessageAtTime(@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); returnfalse; } return enqueueMessage(queue, msg, uptimeMillis); }
booleanenqueueMessage(Message msg, long when){ //如果 Message 没有设置 target 则抛出异常 if (msg.target == null) { thrownew IllegalArgumentException("Message must have a target."); }
synchronized (this) { if (msg.isInUse()) { //如果该 message 已经在使用了,抛出异常 thrownew 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(); returnfalse; }
//将消息标记为在使用中 msg.markInUse(); //将执行时间赋值给 when msg.when = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { //如果 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. //将消息插入到队列中间 //通常来说,我们不需要唤醒事件队列,除非在队列的头是一个屏障消息(target == null),并且要插入的消息是队列中的第一个异步消息 needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; // //下面是个死循环,直到找到队列中的消息的执行时间(when 字段)小于该插入消息的时间的,插在其前面,如果没有,则插入到队列最后面 for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { //如果 p 是异步消息,说明要插入的消息不是第一个异步消息(因为走到这里来说明要插入的消息是插入到了 p 后面了)所以不需要唤醒 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); } } returntrue; }
参数 when 是指需要执行的时间戳(用距离机器开机的时间来计算)
先判断 Message 的 target 是否为空,为空则抛出异常
再判断 Message 是否被使用了,如果该 Message 已经被使用了则抛出异常
再判断是否已经退出了,如果已经退出了则将 Message 回收并返回 false
以上检查无异常后,将 Message 标记为在使用
着重看一下后面的一段代码
判断
p 是否为空(即当前的消息队列为空)
when == 0(即该消息需要立即执行)
when< p.when(即该消息的执行时间早于消息队列的第一条消息的执行时间)
如果满足以上任何一个条件,则将该 Message 插入到队列的头部
否则对 消息队列进行遍历,直到将该消息插入到执行时间都比该消息小的消息后面
可见,MessageQueue 是按照 Message.when 对消息进行排序的,链表中的 Message 按照 when 的大小排序
Message next(){ // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. //如果消息循环已经退出并且被处理了,则会在这里 return //这种情况可能发生在如果应用尝试在退出后重启 looper finallong ptr = mPtr; if (ptr == 0) { returnnull; }
int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); }
synchronized (this) { // Try to retrieve the next message. Return if found. //尝试检索下一条消息,如果找到了就返回 finallong now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; if (msg != null && msg.target == null) { //当前消息队列不为空,且 target 为 null,注意这里的 target 为 null //则从消息队列中找到异步的 Message // Stalled by a barrier. Find the next asynchronous message in the queue. do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); //msg 不为空且为同步的消息,则继续循环直到找到异步的消息 } //此时 msg 就是第一个需要进行处理的 Message(可能是消息屏障后的第一个消息,也可能是原本消息队列中的头,即 mMessage) if (msg != null) { if (now < msg.when) { //如果当前时间还没到消息需要处理的时间,则设置一个延时时间,这里不会 return Message, //如果还没到消息需要处理的时间,所以 for 循环会一直进入这个 case 导致阻塞在这里 // 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 不为 null,说明 msg 为需要处理的异步消息,被提前取出来处理了 //而 prevMsg 就是该消息的前一个消息,现在将 msg.next 链接到 prevMsg.next 的后面,(其实就相当于删除了中间的 msg) //此时的 mMessage 还是原来的 mMessage,下次进入 next() 方法 mMessage 还是原来的那个 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(); returnnull; }
// If first time idle, then get the number of idlers to run. // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future.
//如果第一次闲置,则会获取 idleHandlers 的数量 if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } //如果 idleHandler 数量小于0,则跳过后面的 idleHandler 的逻辑,继续下一个 next() 循环 if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. mBlocked = true; continue; } //否则
if (mPendingIdleHandlers == null) { mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; } //将外部添加进来的 mIdleHandlers 列表拷贝到 mPendingIdleHandlers 数组中 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); }
// Run the idle handlers. // We only ever reach this code block during the first iteration. //运行 idle Handler 的逻辑,这里只可能在第一次 for 循环的迭代时被执行 //(因为后面将 pendingIdleHandlerCount 置为 0了,所以导致后续 pendingIdleHandlerCount 一直为 0) for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; mPendingIdleHandlers[i] = null; // release the reference to the handler
// Reset the idle handler count to 0 so we do not run them again. //将待办的闲置 IdleHandler 的数量置为 0 pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered // so go back and look again for a pending message without waiting. nextPollTimeoutMillis = 0; } }
fun startReflectPostSyncBarrier(looper: Looper){ val method: Method = MessageQueue::class.java.getDeclaredMethod("postSyncBarrier") barrierToken = method.invoke(looper.queue) as Int }
fun stopReflectPostSyncBarrier(looper: Looper){ val method = MessageQueue::class.java .getDeclaredMethod("removeSyncBarrier", Int::class.javaPrimitiveType) method.invoke(looper.queue, barrierToken) }