1. 根view
view的requestLayout
public void requestLayout() {
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
從activity的setContentView中可以看出滋恬,activity的根view是DecorView获列,setContentView的view也是add到id為ID_ANDROID_CONTENT的FrameLayout下毕荐。
在ActivityThread中啟動(dòng)activity時(shí)籍铁,會(huì)調(diào)用handleResumeActivity方法堡距,將DecorView 添加到ViewRootImpl中,DecorView的父類是ViewRootImpl媚送。
final Activity a = r.activity;
View decor = r.window.getDecorView();
ViewManager wm = a.getWindowManager();
wm.addView(decor, l);
WindowManagerImpl 是 wm 的實(shí)現(xiàn)類中燥,wm.addView最終調(diào)用了WindowManagerGlobal 的addView
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
root = new ViewRootImpl(view.getContext(), display);
...
root.setView(view, wparams, panelParentView);//由它去設(shè)置view
...
}
在ViewRootImpl#setView () 會(huì)通過跨進(jìn)程的方式向 WindowManagerService 發(fā)起一個(gè)調(diào)用,將 DecorView 最終添加到 Window 上塘偎。
所以疗涉,調(diào)用父類的requestLayout拿霉,最終會(huì)調(diào)用到根view DecorView,而DecorView的父類是ViewRootImpl咱扣。
2. ViewRootImpl
子view的requestLayout最終還是ViewRootImpl的requestLayout被調(diào)用了绽淘,現(xiàn)在來看requestLayout到底做了什么。
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread(); //檢測(cè)線程
mLayoutRequested = true;
scheduleTraversals();
}
}
檢查當(dāng)前線程是否為主線程闹伪,再調(diào)用scheduleTraversals
void scheduleTraversals() {
//1沪铭、注意這個(gè)標(biāo)志位,多次調(diào)用 requestLayout偏瓤,要這個(gè)標(biāo)志位false才有效
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 2. 同步屏障
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 3. 向 Choreographer 提交一個(gè)任務(wù)
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
//繪制前發(fā)一個(gè)通知
notifyRendererOfFramePending();
//這個(gè)是釋放鎖伦意,先不管
pokeDrawLockIfNeeded();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
//遍歷繪制的開端
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
- 這里先防止多次requestLayout的調(diào)用
- 再通過同步屏障停止同步消息,優(yōu)先執(zhí)行異步消息
- 向 Choreographer 提交一個(gè)任務(wù)硼补,mTraversalRunnable則是要執(zhí)行繪制的回調(diào)
下面先介紹下同步屏障和mTraversalRunnable的執(zhí)行時(shí)機(jī)驮肉。
2.1 同步屏障
在ViewRootImpl中,主要是通過獲取Message設(shè)置setAsynchronous和調(diào)用MessageQueen的postSyncBarrier()來設(shè)置異步任務(wù)已骇,在MessageQueue的next()方法中离钝,如果設(shè)置了同步屏障,則跳過同步任務(wù)褪储,只執(zhí)行異步任務(wù)卵渴。
//MessageQueue
Message next() {
for (;;) {
synchronized (this) {
Message prevMsg = null;
Message msg = mMessages;
//同步屏障,通過target和isAsynchronous來實(shí)現(xiàn)
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
}
}
}
Looper的loop() 中鲤竹,會(huì)調(diào)用MessageQueue的next()來遍歷獲取消息浪读,而next()方法中,當(dāng)msg.target == null且msg.isAsynchronous()為true的Message才會(huì)被獲取到去執(zhí)行辛藻。
- msg.target == null這個(gè)條件是通過mHandler.getLooper().getQueue().postSyncBarrier()發(fā)送了個(gè)target為空的消息來實(shí)現(xiàn)同步屏障碘橘。
- msg.isAsynchronous()為true,通過過獲取Message設(shè)置setAsynchronous(true)
二者缺一不可吱肌,少了其中一個(gè)就是無意義的了痘拆。 只有同步任務(wù)沒有異步任務(wù)去設(shè)置同步屏障,或有異步任務(wù)但不設(shè)置同步屏障氮墨,都是沒有意義的纺蛆。
2.2 Choreographer
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
/**
* Posts a callback to run on the next frame.
* <p>
* The callback runs once then is automatically removed.
* </p>
*
* @param callbackType The callback type.
* @param action The callback action to run during the next frame.
* @param token The callback token, or null if none.
*
* @see #removeCallbacks
* @hide
*/
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
注釋第一句話說的很清楚了,將回調(diào)放在下一幀調(diào)用规揪。接下來簡(jiǎn)單看看具體如何實(shí)現(xiàn)下一幀調(diào)用回調(diào)桥氏。
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
//添加任務(wù)到隊(duì)列
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
//上面的postCallback過來,延遲是0
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
將任務(wù)加入隊(duì)列mCallbackQueues中猛铅,再執(zhí)行scheduleFrameLocked方法
private void scheduleFrameLocked(long now) {
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
}
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
字支。如果運(yùn)行在Looper線程上,則立即調(diào)度vsync;否則祥款,通過Handler發(fā)一個(gè)異步消息到消息隊(duì)列,最終也是到主線程處理月杉,這個(gè)消息時(shí)異步消息刃跛,在先前同步屏障的作用下,會(huì)優(yōu)先執(zhí)行苛萎。
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
FrameDisplayEventReceiver是繼承DisplayEventReceiver
/**
* Schedules a single vertical sync pulse to be delivered when the next
* display frame begins.
*/
public void scheduleVsync() {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
nativeScheduleVsync(mReceiverPtr);
}
}
// Called from native code.
@SuppressWarnings("unused")
private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
onVsync(timestampNanos, builtInDisplayId, frame);
}
還是看注釋桨昙,scheduleVsync方法是調(diào)用JNI方法nativeScheduleVsync請(qǐng)求vsync信號(hào),在下個(gè)vsync信號(hào)來的時(shí)候調(diào)用回調(diào)方法dispatchVsync腌歉。
onVsync則是FrameDisplayEventReceiver中實(shí)現(xiàn)的
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
onVsync發(fā)送了個(gè)異步消息蛙酪,消息傳了個(gè)callback Runnable用于回調(diào),回調(diào)中調(diào)用了doFrame方法翘盖。
doFrame方法會(huì)調(diào)用doCallbacks桂塞,根據(jù)回調(diào)類型從mCallbackQueues取出CallbackRecord,如果回調(diào)類型是Choreographer.CALLBACK_TRAVERSAL馍驯,則執(zhí)行回調(diào)任阁危,也就是ViewRootImpl的mTraversalRunnable。
void doFrame(long frameTimeNanos, int frame) {
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
void doCallbacks(int callbackType, long frameTimeNanos) {
//1.根據(jù)獲取任務(wù)
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
//2.最后一個(gè)類型回調(diào)汰瘫,提交這一幀的時(shí)間
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
if (jitterNanos >= 2 * mFrameIntervalNanos) {
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
+ mFrameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
+ " ms which is more than twice the frame interval of "
+ (mFrameIntervalNanos * 0.000001f) + " ms! "
+ "Setting frame time to " + (lastFrameOffset * 0.000001f)
+ " ms in the past.");
mDebugPrintNextFrameTimeDelta = true;
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
}
}
//3.執(zhí)行回調(diào)任務(wù)
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
c.run(frameTimeNanos);
}
}
圖中 doCallbacks 從 frameTimeNanos2 開始執(zhí)行狂打,執(zhí)行到進(jìn)入 CALLBACK_COMMIT 時(shí),經(jīng)過了2.2幀混弥。
mTraversalRunnable執(zhí)行就是在draw這步趴乡。
2.3 doTraversal
又回到了ViewRootImpl中,上面介紹了TraversalRunnable這個(gè)方法實(shí)際調(diào)用的是doTraversal()蝗拿。
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
//移除同步屏障
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
//執(zhí)行繪制
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
同步屏障是為了給Choreographer中的異步消息讓步晾捏,當(dāng)回調(diào)到這里時(shí),可以關(guān)閉同步屏障哀托,執(zhí)行后續(xù)的方法performTraversals了粟瞬。
private void performTraversals() {
//mView就是setContentView的view
final View host = mView;
// mAttachInfo 賦值給View
host.dispatchAttachedToWindow(mAttachInfo, 0);
if (!mStopped || mReportNextDraw) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
updatedConfiguration) {
//開始第一次測(cè)量大小
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
//如果有設(shè)置權(quán)重,比如LinearLayout設(shè)置了weight萤捆,需要測(cè)量?jī)纱? if (measureAgain) {
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
}
//布局
performLayout(lp, mWidth, mHeight);
if (triggerGlobalLayoutListener) {
mAttachInfo.mRecomputeGlobalAttributes = false;
//調(diào)用dispatchOnGlobalLayout
mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
}
//繪制
performDraw();
}
分別調(diào)用了performMeasure裙品,performLayout和performDraw,這三個(gè)方法開始遍歷子view進(jìn)行測(cè)量俗或,布局和繪制市怎。
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
if (mView == null) {
return;
}
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
//開始測(cè)量
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
如何實(shí)現(xiàn)測(cè)量,可以看看Measure要知道的點(diǎn)
總結(jié)
View.requestLayout -> ViewRootImpl.requestLayout -> ViewRootImpl.scheduleTraversals -> Choreographer.postCallback -> DisplayEventReceiver.scheduleVsync() -> Choreographer.doFrame -> Choreographer.doCallbacks ->ViewRootImpl.doTraversal -> ViewRootImpl.performTraversals
從子view的requestLayout辛慰,到ViewRootImpl的requestLayout区匠,在給Choreographer添加任務(wù),Choreographer通過DisplayEventReceiver來監(jiān)聽vsync信號(hào),回調(diào)執(zhí)行ViewRootImpl的doTraversal開始進(jìn)行繪制驰弄。