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

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

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

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

ViewRootImpl位于視圖層次結構的頂部,負責View和WindowManager之間的通信。d5z28資訊網——每日最新資訊28at.com

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

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

scheduleTraversals

scheduleTraversals()方法負責將一次視圖遍歷(traversal)排期到其調度計劃中,但并不會立即執行遍歷操作。方法被許多操作所調用,比如當視圖的大小、位置等屬性發生變化時,或者當調用requestLayout()、invalidate()等方法時,都會觸發scheduleTraversals()。作用是將視圖的測量、布局和繪制操作(即遍歷操作)放入待執行隊列中,并注冊一個底層的刷新信號監聽器。d5z28資訊網——每日最新資訊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);        //調用父容器的方法,向上傳遞事件        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()操作,并將其加入到主線程的消息隊列中。然后,主線程會從消息隊列中取出并執行這個操作,進而觸發視圖的測量、布局和繪制流程。d5z28資訊網——每日最新資訊28at.com

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()原生方法通知屏幕進行繪制。d5z28資訊網——每日最新資訊28at.com

performTraversals

performTraversals()方法負責啟動視圖的測量(measure)、布局(layout)和繪制(draw)流程。當需要創建視圖、視圖參數改變或界面需要刷新時,可能會從根視圖DecorView開始重新進行測量、布局和繪制,這時就會調用到performTraversals()方法。d5z28資訊網——每日最新資訊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();    }}

圖片圖片d5z28資訊網——每日最新資訊28at.com

  1. 「測量(Measure)」:在這個階段,系統會遍歷整個視圖樹,計算每個視圖的大小。這個過程中會用到MeasureSpec,每個MeasureSpec都包含了一個測量模式和測量大小,測量模式主要有三種:EXACTLY(父視圖已經確定了子視圖的確切大小)、AT_MOST(子視圖的大小有一個最大值限制)和UNSPECIFIED(父視圖對子視圖的大小沒有要求)。
  2. 「布局(Layout)」:在測量完成后,系統會為每個視圖確定其在屏幕上的精確位置。這個過程中,父視圖會根據測量階段得到的子視圖大小以及自身的布局參數,計算出子視圖應該放置的位置。
  3. 「繪制(Draw)」:系統會遍歷整個視圖樹,根據每個視圖的繪制參數(如顏色、形狀等)將其繪制到屏幕上。這個過程中,視圖會按照其在視圖樹中的層次順序進行繪制,先繪制父視圖,再繪制子視圖。
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方法進行界面刷新。d5z28資訊網——每日最新資訊28at.com

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

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

上一篇: Vue3 實現最近很火的酷炫功能:卡片懸浮發光

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

標簽:
  • 熱門焦點
  • 盧偉冰長文解析K60至尊版 對Redmi有著里程碑式的意義

    在今天的Redmi后性能時代戰略發布會結束之后,Redmi總經理盧偉冰又帶來了一篇長文,詳解了為什么 Redmi 要開啟后性能時代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • 官方承諾:K60至尊版將會首批升級MIUI 15

    全新的MIUI 15今天也有了消息,在官宣了K60至尊版將會搭載天璣9200+處理器和獨顯芯片X7的同時,Redmi給出了官方承諾,K60至尊重大更新首批升級,會首批推送MIUI 15。也就是說雖然
  • Mate60手機殼曝光 致敬自己的經典設計

    8月3日消息,今天下午博主數碼閑聊站帶來了華為Mate60的第三方手機殼圖,可以讓我們在真機發布之前看看這款華為全新旗艦的大致輪廓。從曝光的圖片看,Mate 60背后攝像頭面積依然
  • 7月安卓手機好評榜:三星S23Ultra好評率第一

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年7月1日至7月31日,僅限國內市場。第一名:三星Galaxy S23 Ultra好評率:95.71%在即將迎來新
  • 7月安卓手機性能榜:紅魔8S Pro再奪榜首

    7月份的手機市場風平浪靜,除了紅魔和努比亞帶來了兩款搭載驍龍8Gen2領先版處理器的新機之外,別的也想不到有什么新品了,這也正常,通常6月7月都是手機廠商修整的時間,進入8月份之
  • 摸魚心法第一章——和配置文件說拜拜

    為了能摸魚我們團隊做了容器化,但是帶來的問題是服務配置文件很麻煩,然后大家在群里進行了“親切友好”的溝通圖片圖片圖片圖片對比就對比,簡單對比下獨立配置中心和k8s作為配
  • 十個簡單但很有用的Python裝飾器

    裝飾器(Decorators)是Python中一種強大而靈活的功能,用于修改或增強函數或類的行為。裝飾器本質上是一個函數,它接受另一個函數或類作為參數,并返回一個新的函數或類。它們通常用
  • 阿里瓴羊One推出背后,零售企業迎數字化新解

    作者:劉曠近年來隨著數字經濟的高速發展,各式各樣的SaaS應用服務更是層出不窮,但本質上SaaS大多局限于單一業務流層面,對用戶核心關切的增長問題等則沒有提供更好的解法。在Saa
  • iQOO Neo8 Pro真機諜照曝光:天璣9200+和V1+旗艦雙芯加持

    去年10月,iQOO推出了iQOO Neo7系列機型,不僅搭載了天璣9000+,而且是同價位唯一一款天璣9000+直屏旗艦,一經上市便受到了用戶的廣泛關注。在時隔半年后,
Top