日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

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

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

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

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

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

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

scheduleTraversals

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

performTraversals

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

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

  1. 「測量(Measure)」:在這個階段,系統會遍歷整個視圖樹,計算每個視圖的大小。這個過程中會用到MeasureSpec,每個MeasureSpec都包含了一個測量模式和測量大小,測量模式主要有三種:EXACTLY(父視圖已經確定了子視圖的確切大?。T_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方法進行界面刷新。EEF28資訊網——每日最新資訊28at.com

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

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

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

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

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美日本不卡| 久久成人在线| 99国产精品久久久久久久久久| 91久久国产自产拍夜夜嗨| 日韩视频免费观看高清完整版| 亚洲一级电影| 久久久99国产精品免费| 欧美国产成人在线| 欧美日韩国产成人| 国产精品专区第二| 在线播放国产一区中文字幕剧情欧美| 亚洲欧洲一区二区天堂久久| 亚洲一区二区在线免费观看| 久久久噜噜噜久噜久久| 欧美日韩亚洲91| 国产自产高清不卡| 一本色道久久综合亚洲精品高清| 欧美一区二区视频在线| 欧美经典一区二区三区| 国产区精品在线观看| 亚洲精品欧美精品| 久久av资源网站| 欧美精品久久久久a| 国产日本欧美一区二区三区在线 | 亚洲午夜精品久久久久久浪潮 | 亚洲精品中文字幕有码专区| 亚洲欧美日韩国产| 欧美电影电视剧在线观看| 国产精品亚洲美女av网站| 亚洲黄色成人| 久久成人18免费观看| 欧美人与性动交α欧美精品济南到| 午夜老司机精品| 毛片精品免费在线观看| 国产精品久久久久久久久动漫 | 欧美一二三区精品| 欧美日韩1080p| 国内精品视频久久| 亚洲免费影视| 欧美理论电影在线播放| 一区二区三区在线免费视频| 亚洲综合激情| 欧美日本亚洲韩国国产| 精品1区2区| 欧美有码在线视频| 国产精品第一区| 亚洲精品欧美一区二区三区| 久久久国产精品一区二区中文 | 国产欧美日韩伦理| 一区二区三区成人| 欧美第一黄网免费网站| 一区在线播放视频| 久久精品国产亚洲精品| 国产精品嫩草影院一区二区| 99精品热视频| 欧美国产先锋| 亚洲高清不卡| 久久影视精品| 韩国久久久久| 久久精品二区亚洲w码| 国产精品一区二区欧美| 亚洲性线免费观看视频成熟| 欧美日韩另类视频| 亚洲美女黄色片| 欧美黄色免费| 91久久在线播放| 欧美成人dvd在线视频| 在线成人h网| 久色成人在线| 亚洲大胆av| 蜜桃久久精品一区二区| 在线观看欧美黄色| 久久综合久久综合九色| 激情综合色丁香一区二区| 久久精品久久99精品久久| 国产亚洲一区二区在线观看| 欧美一区影院| 国产网站欧美日韩免费精品在线观看| 亚洲欧美在线高清| 国产欧美精品| 欧美影院一区| 国产中文一区| 久久一区视频| 亚洲啪啪91| 欧美女激情福利| 一区二区欧美在线观看| 欧美视频你懂的| 亚洲免费在线精品一区| 国产精品久线观看视频| 午夜精品久久久久久99热软件| 国产伦精品一区二区三区高清| 亚洲欧美日韩在线一区| 国产午夜精品视频| 久久免费少妇高潮久久精品99| 激情一区二区三区| 免费视频最近日韩| 亚洲另类视频| 欧美午夜一区二区福利视频| 亚洲男女自偷自拍| 国产三级精品在线不卡| 久久男人资源视频| 91久久国产综合久久| 欧美日韩第一页| 亚洲综合色激情五月| 国产亚洲成年网址在线观看| 久久亚洲综合色| 亚洲日本欧美天堂| 国产精品草草| 欧美一区国产在线| 亚洲福利视频一区| 欧美理论片在线观看| 亚洲小说欧美另类社区| 国产性猛交xxxx免费看久久| 另类天堂av| 中日韩午夜理伦电影免费| 国产模特精品视频久久久久| 久久偷窥视频| 一区电影在线观看| 国产亚洲福利一区| 欧美xxx成人| 亚洲天堂黄色| 韩日欧美一区| 欧美区高清在线| 欧美呦呦网站| 亚洲精品国产拍免费91在线| 国产精品久久久亚洲一区 | 亚洲成人在线视频网站| 欧美日韩高清一区| 欧美在线视频免费播放| 亚洲国产精品va在看黑人| 欧美日韩综合另类| 久久精品91| aa亚洲婷婷| 国产综合色在线| 欧美日本精品一区二区三区| 欧美在线视频网站| 亚洲精品美女在线| 国产欧美日韩激情| 欧美电影免费观看| 欧美一区激情视频在线观看| 亚洲美女免费视频| 国精品一区二区三区| 欧美日韩亚洲视频| 久久视频在线视频| 亚洲一区区二区| 亚洲国产精品ⅴa在线观看| 国产欧美日韩一区二区三区在线观看| 欧美成人精品一区| 久久疯狂做爰流白浆xx| 一区二区三区日韩欧美| 在线视频国内自拍亚洲视频| 国产欧美日韩综合精品二区| 欧美片第一页| 久久综合久久综合久久| 午夜精品久久久久久久| 亚洲免费电影在线| 樱桃国产成人精品视频| 国产精自产拍久久久久久| 欧美日韩久久久久久| 免费91麻豆精品国产自产在线观看| 亚洲欧美日韩一区二区三区在线观看 | 午夜精品视频网站| 亚洲精品一区二区三区在线观看 | 欧美成人久久| 久久精品毛片| 亚洲欧美影音先锋| 在线视频精品一| 亚洲国产美女| 红桃视频成人| 国产视频精品网| 国产精品伦理| 国产精品mm| 欧美日韩成人综合在线一区二区 | 欧美亚洲综合久久| 亚洲午夜一区二区三区| 亚洲乱码国产乱码精品精可以看| 久久九九有精品国产23| 亚洲欧美制服中文字幕| 一区二区三区色| 日韩网站在线观看| 亚洲黄网站在线观看| 在线观看福利一区| 国产主播喷水一区二区| 国产婷婷色一区二区三区在线| 国产精品视区| 国产精品免费视频xxxx| 欧美午夜剧场| 欧美性开放视频| 欧美三级免费| 欧美色欧美亚洲高清在线视频| 欧美日本一道本| 欧美日韩国产小视频| 欧美日本韩国一区| 欧美人妖另类| 欧美日韩国产三区| 欧美日韩日本视频| 欧美区视频在线观看| 欧美精品在线一区二区三区| 欧美激情一区二区| 欧美福利视频| 欧美日韩国产综合视频在线观看| 欧美成人午夜激情在线| 免费人成网站在线观看欧美高清| 美女免费视频一区|