AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

ViewRootImpl如何負責管理繪制視圖樹和刷新界面

來源: 責編: 時間:2024-05-22 17:14:37 150觀看
導讀ViewRootImpl位于視圖層次結(jié)構(gòu)的頂部,負責View和WindowManager之間的通信。視圖繪制:負責調(diào)用View樹的繪制流程,包括測量(measure)、布局(layout)和繪制(draw)等操作。監(jiān)聽View樹的改變,并根據(jù)需要觸發(fā)相應的繪制操作,確保界面的

ViewRootImpl位于視圖層次結(jié)構(gòu)的頂部,負責View和WindowManager之間的通信。EoZ28資訊網(wǎng)——每日最新資訊28at.com

  1. 視圖繪制:負責調(diào)用View樹的繪制流程,包括測量(measure)、布局(layout)和繪制(draw)等操作。監(jiān)聽View樹的改變,并根據(jù)需要觸發(fā)相應的繪制操作,確保界面的及時更新。
  2. 事件分發(fā):負責將輸入的各種事件(如觸摸事件、按鍵事件等)分發(fā)給正確的View處理。根據(jù)觸摸事件的位置信息,逐層遍歷View樹,找到最合適的View來處理事件。將處理結(jié)果返回給系統(tǒng),以便進行后續(xù)的處理,如滾動、點擊等。
  3. 窗口管理:承擔Android窗口管理的一部分職責。負責創(chuàng)建和管理窗口,將窗口與ViewRootImpl進行綁定。當窗口需要顯示或隱藏時,ViewRootImpl會相應地調(diào)整界面的顯示狀態(tài)。

ViewRootImpl關聯(lián)了多個類和接口,IWindowSession、Choreographer及其FrameCallback接口等。IWindowSession用于客戶端和WindowManagerService之間進行窗口管理操作的接口,允許ViewRootImpl與WindowManagerService進行通信,執(zhí)行如添加、刪除、更新窗口等操作。EoZ28資訊網(wǎng)——每日最新資訊28at.com

scheduleTraversals

scheduleTraversals()方法負責將一次視圖遍歷(traversal)排期到其調(diào)度計劃中,但并不會立即執(zhí)行遍歷操作。方法被許多操作所調(diào)用,比如當視圖的大小、位置等屬性發(fā)生變化時,或者當調(diào)用requestLayout()、invalidate()等方法時,都會觸發(fā)scheduleTraversals()。作用是將視圖的測量、布局和繪制操作(即遍歷操作)放入待執(zhí)行隊列中,并注冊一個底層的刷新信號監(jiān)聽器。EoZ28資訊網(wǎng)——每日最新資訊28at.com

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);        //調(diào)用父容器的方法,向上傳遞事件        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;                }            }            //調(diào)用ViewGrup的invalidateChildInParent,如果已經(jīng)達到最頂層view,則調(diào)用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系統(tǒng)中用于同步屏幕刷新的信號),系統(tǒng)會從待執(zhí)行隊列中取出對應的scheduleTraversals()操作,并將其加入到主線程的消息隊列中。然后,主線程會從消息隊列中取出并執(zhí)行這個操作,進而觸發(fā)視圖的測量、布局和繪制流程。EoZ28資訊網(wǎng)——每日最新資訊28at.com

private void scheduleFrameLocked(long now) {    if (!mFrameScheduled) {        mFrameScheduled = true;        if (USE_VSYNC) {            //這里判斷,當前執(zhí)行的線程是否是創(chuàng)建該Choreographer的線程,如果是直接執(zhí)行。否則通過handler 發(fā)送到 創(chuàng)建該Choreographer的線程去執(zhí)行。            if (isRunningOnLooperThreadLocked()) {                scheduleVsyncLocked();            } else {                //這條message 最后處理還是調(diào)用到了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()方法會被調(diào)用。方法會執(zhí)行實際的測量、布局和繪制操作。首先會調(diào)用measureHierarchy()方法進行測量,然后調(diào)用performLayout()方法進行布局,最后調(diào)用draw()方法進行繪制。這些操作會按照順序執(zhí)行,以確保視圖能夠正確地顯示在屏幕上。最終通過nativeScheduleVsync()原生方法通知屏幕進行繪制。EoZ28資訊網(wǎng)——每日最新資訊28at.com

performTraversals

performTraversals()方法負責啟動視圖的測量(measure)、布局(layout)和繪制(draw)流程。當需要創(chuàng)建視圖、視圖參數(shù)改變或界面需要刷新時,可能會從根視圖DecorView開始重新進行測量、布局和繪制,這時就會調(diào)用到performTraversals()方法。EoZ28資訊網(wǎng)——每日最新資訊28at.com

private void performTraversals() {    ...    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);    ...    performLayout(lp, desiredWindowWidth, desiredWindowHeight);    ...     performDraw();}void doTraversal() {      //防止重入    if (mTraversalScheduled) {        mTraversalScheduled = false;        //移除同步屏障        mHandler.getLooper().getQueue()                    .removeSyncBarrier(mTraversalBarrier);        performTraversals();    }}

圖片圖片EoZ28資訊網(wǎng)——每日最新資訊28at.com

  1. 「測量(Measure)」:在這個階段,系統(tǒng)會遍歷整個視圖樹,計算每個視圖的大小。這個過程中會用到MeasureSpec,每個MeasureSpec都包含了一個測量模式和測量大小,測量模式主要有三種:EXACTLY(父視圖已經(jīng)確定了子視圖的確切大小)、AT_MOST(子視圖的大小有一個最大值限制)和UNSPECIFIED(父視圖對子視圖的大小沒有要求)。
  2. 「布局(Layout)」:在測量完成后,系統(tǒng)會為每個視圖確定其在屏幕上的精確位置。這個過程中,父視圖會根據(jù)測量階段得到的子視圖大小以及自身的布局參數(shù),計算出子視圖應該放置的位置。
  3. 「繪制(Draw)」:系統(tǒng)會遍歷整個視圖樹,根據(jù)每個視圖的繪制參數(shù)(如顏色、形狀等)將其繪制到屏幕上。這個過程中,視圖會按照其在視圖樹中的層次順序進行繪制,先繪制父視圖,再繪制子視圖。
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 回調(diào)里面去,等待回調(diào)執(zhí)行。        mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);                    //now=0 ,走進scheduleFrameLocked()方法內(nèi)        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內(nèi)部類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 {        // 這里也即是調(diào)用了TraservalRunnable的run方法,也即是三個繪制流程        ((Runnable)action).run();    }}

mHandler是當前主線程的handler,當接收到onVsync信號的時候,將自己封裝到Message中,等到Looper處理,最后Looper處理消息的時候就會調(diào)用run方法最終從mCallbackQueues取回之前添加的任務再執(zhí)行run方法,也就是TraservalRunnable的run方法。最終觸發(fā)performTraversals方法進行界面刷新。EoZ28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-90041-0.htmlViewRootImpl如何負責管理繪制視圖樹和刷新界面

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Vue3 實現(xiàn)最近很火的酷炫功能:卡片懸浮發(fā)光

下一篇: 我們忘記了前端基礎知識

標簽:
  • 熱門焦點
Top