前言
对于Handler机制,想必大家都已经非常熟悉了吧,从迈进Android开发这扇大门的时候,就不停的研究和使用它,同样的这也是Android系统架构的精髓之一。然而在我们使用的时候,往往会忽略掉一些不常见却又很重要的内容,今天就来讲一讲经常被忽略的同步屏障以及异步消息。
制流程中窥视handler同步屏障
为了引出今天的主题,我们先来看看ui的渲染流程吧。在Android的绘制流程中,ViewRootImpl这个类发挥了非常重要的作用,首先我们看一下这个类中比较重要的一个方法requestLayout(),
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
//校验主线程
checkThread();
mLayoutRequested = true;
//调用这个方法启动绘制流程
scheduleTraversals();
}
}
requestLayout()中会通过checkThread()方法检查发起布局请求的线程是否为主线程(校验ViewRootImpl构造时记录的mThread, 和当前线程是否一致),之后,在调用scheduleTraversals()的时候 postSyncBarrier添加同步消息屏障
@UnsupportedAppUsage
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
//1. 往主线程的Handler对应的MessageQueue发送一个同步屏障消息
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//2.将mTraversalRunnable保存到Choreographer中
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
...
//在doTraversal方法中移除同步消息屏障
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
//移除同步屏障
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
...
}
}
在这个方法中,涉及到三个比较重要的信息
- mTraversalRunnable
- Choreographer编舞者
- 同步屏障消息
-
首先看mTra