ViewRootImpl位于視圖層次結構的頂部,負責View和WindowManager之間的通信。
ViewRootImpl關聯了多個類和接口,IWindowSession、Choreographer及其FrameCallback接口等。IWindowSession用于客戶端和WindowManagerService之間進行窗口管理操作的接口,允許ViewRootImpl與WindowManagerService進行通信,執行如添加、刪除、更新窗口等操作。
scheduleTraversals()方法負責將一次視圖遍歷(traversal)排期到其調度計劃中,但并不會立即執行遍歷操作。方法被許多操作所調用,比如當視圖的大小、位置等屬性發生變化時,或者當調用requestLayout()、invalidate()等方法時,都會觸發scheduleTraversals()。作用是將視圖的測量、布局和繪制操作(即遍歷操作)放入待執行隊列中,并注冊一個底層的刷新信號監聽器。
public void invalidate(boolean invalidateCache) { invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);}void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate) { ... // Propagate the damage rectangle to the parent view. final AttachInfo ai = mAttachInfo; final ViewParent p = mParent; if (p != null && ai != null && l < r && t < b) { final Rect damage = ai.mTmpInvalRect; damage.set(l, t, r, b); //調用父容器的方法,向上傳遞事件 p.invalidateChild(this, damage); } ...}public final void invalidateChild(View child, final Rect dirty) { ..... ViewParent parent = this; do { View view = null; if (parent instanceof View) { view = (View) parent; } if (drawAnimation) { if (view != null) { view.mPrivateFlags |= PFLAG_DRAW_ANIMATION; } else if (parent instanceof ViewRootImpl) { ((ViewRootImpl) parent).mIsAnimating = true; } } // If the parent is dirty opaque or not dirty, mark it dirty with the opaque // flag coming from the child that initiated the invalidate if (view != null) { if ((view.mViewFlags & FADING_EDGE_MASK) != 0 && view.getSolidColor() == 0) { opaqueFlag = PFLAG_DIRTY; } if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) { view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag; } } //調用ViewGrup的invalidateChildInParent,如果已經達到最頂層view,則調用ViewRootImpl的invalidateChildInParent。 parent = parent.invalidateChildInParent(location, dirty); if (view != null) { // Account for transform on current parent Matrix m = view.getMatrix(); if (!m.isIdentity()) { RectF boundingRect = attachInfo.mTmpTransformRect; boundingRect.set(dirty); m.mapRect(boundingRect); dirty.set((int) Math.floor(boundingRect.left), (int) Math.floor(boundingRect.top), (int) Math.ceil(boundingRect.right), (int) Math.ceil(boundingRect.bottom)); } } } while (parent != null); }}
當VSYNC信號到來時(VSYNC信號是Android系統中用于同步屏幕刷新的信號),系統會從待執行隊列中取出對應的scheduleTraversals()操作,并將其加入到主線程的消息隊列中。然后,主線程會從消息隊列中取出并執行這個操作,進而觸發視圖的測量、布局和繪制流程。
private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; if (USE_VSYNC) { //這里判斷,當前執行的線程是否是創建該Choreographer的線程,如果是直接執行。否則通過handler 發送到 創建該Choreographer的線程去執行。 if (isRunningOnLooperThreadLocked()) { scheduleVsyncLocked(); } else { //這條message 最后處理還是調用到了scheduleVsyncLocked方法 Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC); msg.setAsynchronous(true); mHandler.sendMessageAtFrontOfQueue(msg); } } else { final long nextFrameTime = Math.max( mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms."); } Message msg = mHandler.obtainMessage(MSG_DO_FRAME); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, nextFrameTime); } }}private void scheduleVsyncLocked() { mDisplayEventReceiver.scheduleVsync();}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); }}
在這個過程中,performTraversals()方法會被調用。方法會執行實際的測量、布局和繪制操作。首先會調用measureHierarchy()方法進行測量,然后調用performLayout()方法進行布局,最后調用draw()方法進行繪制。這些操作會按照順序執行,以確保視圖能夠正確地顯示在屏幕上。最終通過nativeScheduleVsync()原生方法通知屏幕進行繪制。
performTraversals()方法負責啟動視圖的測量(measure)、布局(layout)和繪制(draw)流程。當需要創建視圖、視圖參數改變或界面需要刷新時,可能會從根視圖DecorView開始重新進行測量、布局和繪制,這時就會調用到performTraversals()方法。
private void performTraversals() { ... performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); ... performLayout(lp, desiredWindowWidth, desiredWindowHeight); ... performDraw();}void doTraversal() { //防止重入 if (mTraversalScheduled) { mTraversalScheduled = false; //移除同步屏障 mHandler.getLooper().getQueue() .removeSyncBarrier(mTraversalBarrier); performTraversals(); }}
圖片
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();void scheduleTraversals() { if (!mTraversalScheduled) { //移除同步屏障 mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); }}void unscheduleTraversals() { mChoreographer.removeCallbacks( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); }}public void postCallback(int callbackType, Runnable action, Object token) { postCallbackDelayed(callbackType, action, token, 0);}public void postCallbackDelayed(int callbackType, Runnable action, Object token, long delayMillis) { ... postCallbackDelayedInternal(callbackType, action, token, delayMillis);}private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { .... synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; //把 任務添加到了mCallbackQueues 回調里面去,等待回調執行。 mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); //now=0 ,走進scheduleFrameLocked()方法內 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); } }}//Choreographer內部類DisplayEventReceiver,重寫了onVsync方法@Overridepublic 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);}public void run() { mHavePendingVsync = false; doFrame(mTimestampNanos, mFrame);}// Choreographervoid doFrame(long frameTimeNanos, int frame) { ... doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);}void doCallbacks(int callbackType, long frameTimeNanos) { CallbackRecord callbacks; // 從mCallbackQueues取出 callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now / TimeUtils.NANOS_PER_MS); for (CallbackRecord c = callbacks; c != null; c = c.next) { c.run(frameTimeNanos); }}// CallbackRecordpublic void run(long frameTimeNanos) { if (token == FRAME_CALLBACK_TOKEN) { ((FrameCallback)action).doFrame(frameTimeNanos); } else { // 這里也即是調用了TraservalRunnable的run方法,也即是三個繪制流程 ((Runnable)action).run(); }}
mHandler是當前主線程的handler,當接收到onVsync信號的時候,將自己封裝到Message中,等到Looper處理,最后Looper處理消息的時候就會調用run方法最終從mCallbackQueues取回之前添加的任務再執行run方法,也就是TraservalRunnable的run方法。最終觸發performTraversals方法進行界面刷新。
本文鏈接:http://www.tebozhan.com/showinfo-26-90041-0.htmlViewRootImpl如何負責管理繪制視圖樹和刷新界面
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
下一篇: 我們忘記了前端基礎知識