You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.3 KiB

---
消息屏障
---
```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. 异步消息