--- 消息屏障 --- ```java // 插入屏障 private int postSyncBarrier(long when){ synchronized(this){ final int token = mNextBarrierToken++; final Message msg = Message.obtain(); msg.markInUse(); msg.when = when; msg.arg1 = token; return token; } } // 删除屏障 public void removeSyncBarrier(int token){ synchronized(this){ if(needWake && !mQuitting){ nativeWake(mPtr); } } } // 处理屏障 Message next(){ for(;;){ nativePollOnce(ptr, nextPollTimeoutMillis); synchronized(this){ // 如果第一条消息就是屏障,就往后遍历,看看有没有异步消息 // 如果没有,就无限休眠,等待被别人唤醒 // 如果有,就看离这个消息触发时间还有多久,设置一个超时,继续休眠 continue; } } } boolean enqueueMessage(Message msg, long when){ synchronized(this){ // 给消息插到消息队列 // 如果插到队列头了,如果当前线程是休眠的,就要唤醒他 // 如果没插到队列头,如果当前线程是休眠的,并且队列头是屏障 // 并且当前消息是最早的一条异步消息,就要唤醒线程 if(needWake){ nativeWake(mPtr); } } return true; } ``` #### 看几个问题? 1. 消息队列为空的时候,插一个屏障,会触发 IdleHandler 嘛? 2. 如果删除了屏障,消息队列为空了,会触发 IdleHandler 嘛? 3. 如果消息队列只有一个屏障消息,插一个普通消息会 IdleHandler 嘛? 4. 如果消息队列只有一个屏障消息,插一个异步消息会 IdleHandler 嘛? Framework 里面哪里用到了消息屏障? ```java void scheduleTraversals(){ if(!mTraversalScheduled){ mTraversalScheduled = true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); } } void doTraversal(){ if(mTraversalScheduled){ mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); performTraversals(); } } ``` #### 总结 1. 消息屏障 2. 异步消息