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.
 

2.3 KiB

消息屏障
// 插入屏障
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 里面哪里用到了消息屏障?

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