Message中有一个方法叫Message.setAsynchronous,表示发送异步消息,然而他需要插入同步屏障才能生效,那什么是同步屏障呢?
一般来说,Message如果按顺序进行发送的,并不是设置delay的话,运行都是同步的,然而在某些特殊时期,为了提高某个消息的优先级,防止中途插入的Message导致任务调度延迟,会使用异步Message,当调用postSyncBarrier之后,之后的任意同步消息都不再执行,期间只能执行异步消息,直到移除了同步屏障。
插入屏障:MessageQueue.postSyncBarrier
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
private int postSyncBarrier(long when) { synchronized (this) { final int token = mNextBarrierToken++; final Message msg = Message.obtain(); msg.markInUse(); msg.when = when; msg.arg1 = token; Message prev = null; Message p = mMessages; //寻找第一个运行目标时间大于当前插入目标的节点 //简单的说就是链表的插入排序,把时间触发早的排在前面 if (when != 0) { while (p != null && p.when <= when) { prev = p; p = p.next; } } //插入节点,注意插入的节点msg里的handler==null; if (prev != null) { // invariant: p == prev.next msg.next = p; prev.next = msg; } else { msg.next = p; mMessages = msg; } return token; } } |
往链表里插入了一个奇怪的msg,他的target为null
消息循环:MessageQueue.next
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
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. final long ptr = mPtr; if (ptr == 0) { return null; } 是否有idlehandler要处理 int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } //通过linux的底层epoll挂住 nativePollOnce(ptr, nextPollTimeoutMillis); 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; } while (msg != null && !msg.isAsynchronous()); //找到第一个异步消息 } if (msg != null) { //没到点,可能是被主动唤醒而不是到点唤醒的 if (now < msg.when) { //计算新的时间,然后设置给底层epoll,告诉他下次要什么时候唤醒 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { //处理这个消息,把他从链表移除移除 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; } //省略下面关于idlehandle的处理 } } |
遍历消息,也就是忽略所有非异步消息,只取出异步消息