前面有学习了Android绘制的三大流程:merge、layout、draw,但是一直都没有搞清楚绘制到显示的整体流程。借此机会,记录下自己学习过程。
我们都知道,一次完整的录制时都是从ViewRootImpl的scheduleTraversals()开始,即使调用invalidate()也是如此。
scheduleTraversals
// ViewRootImpl.java
void scheduleTraversals() {
// mTraversalScheduled阻止了多次调用
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 加入同步屏障
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 加入一个callback到mChoreographer
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
可以看到scheduleTraversals()主要做了两件事:
- 往当前线程的Loop加入同步屏障
- 封装了一个mTraversalRunnable加入到mChoreographer
这里就引申出来三个问题:
- mTraversalRunnable是什么?
- mChoreographer是什么?
- 同步屏障是什么?有什么用?
mTraversableRunnable
其实TraversableRunnable分装着就是measure、layout、draw三大流程。
// ViewRootImpl
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
// 移除同步屏障
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
performTraversals();
}
}
private void performTraversals() {
final View host = mView;
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw(<