Android GUI之View繪製流程

來源:互聯網
上載者:User

標籤:

  在上篇文章中,我們通過跟蹤源碼,我們瞭解了Activity、Window、DecorView以及View之間的關係(查看文章:http://blog.csdn.net/jerehedu/article/details/47021541)。那麼整個Activity的介面到底是如何繪製出來的呢?既然DecorView作為Activity的頂層介面視圖,那麼整個介面的繪製工作應該從它開始,下面我們繼續跟蹤源碼,看看是不是這樣的。

  Activity在啟動過程中會調用主線程ActivityThread中的方法performLaunchActivity和handleResumeActivity。在方法handleResumeActivity中會將建立的DecorView和WindowManagerImpl對象關聯起來,關鍵源碼部分如下:

public final class ActivityThread {   ……    final void handleResumeActivity(IBinder token,            boolean clearHide, boolean isForward, boolean reallyResume) {      ……            if (r.window == null && !a.mFinished && willBeVisible) {                r.window = r.activity.getWindow();                View decor = r.window.getDecorView();                decor.setVisibility(View.INVISIBLE);                ViewManager wm = a.getWindowManager();                WindowManager.LayoutParams l = r.window.getAttributes();                a.mDecor = decor;                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;                l.softInputMode |= forwardBit;                if (a.mVisibleFromClient) {                    a.mWindowAdded = true;                    wm.addView(decor, l);                }            } ……    }}

  WindowManagerImpl關鍵代碼:

    public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();……@Overridepublic void addView(View view, ViewGroup.LayoutParams params) {      mGlobal.addView(view, params, mDisplay, mParentWindow);}……}

  WindowManagerGlobal關鍵代碼:

public final class WindowManagerGlobal {    ……    public void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {           ……        ViewRootImpl root;        View panelParentView = null;……        root.setView(view, wparams, panelParentView);           ……    }}

  根據源碼調用關係,可得:

  ,我們可以看出在ActivityThread中產生的DecorView經過WindowManagerImpl、WindowManagerGlobal,最終調用了ViewRootImpl中的setView方法,將DecorView設定賦值給了ViewRootImpl中的mView屬性。通過追蹤ViewRootImpl我們發現最終調用了performTraversals方法,該方法關鍵代碼如下:

private void performTraversals() {        // cache mView since it is used so much below...        final View host = mView;        ……        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);        ……        performLayout(lp, desiredWindowWidth, desiredWindowHeight);        ……        performDraw();        ……}

  從上述源碼中我們可以看出,performTraversals實際上依次調用了三個關鍵的方法,分別是performMeasure,performLayout、performDraw。

  1、方法performMeasure,內部實際上調用了mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);不要忘了此處的mView正是我們傳遞進來的DecorView,該方法用於測量View的大小。關鍵源碼如下:

        private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");        try {            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }    }

  2、方法performLayout,內部實際上調用了host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());該方法用於確定視圖的位置。關鍵源碼如下:

    private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,            int desiredWindowHeight) {        mLayoutRequested = false;        mScrollMayChange = true;        mInLayout = true;        final View host = mView;        ……        try {            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());            mInLayout = false;            int numViewsRequestingLayout = mLayoutRequesters.size();            if (numViewsRequestingLayout > 0) {              ……                if (validLayoutRequesters != null) {                    // Set this flag to indicate that any further requests are happening during                   ……                    host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());                   ……                    }                }            }        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }        mInLayout = false;    }

  3、方法performDraw,用於繪製視圖,追蹤源碼發現,最終調用了mView.draw(canvas)方法,用於繪製。

  經過上述過程基本上可以確定View的繪製流程,流程圖具體如下:

 

  疑問諮詢或技術交流,請加入官方QQ群: (452379712)

 

傑瑞教育
出處:http://blog.csdn.net/jerehedu/ 
本文著作權歸煙台傑瑞教育科技有限公司和CSDN共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。 

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android GUI之View繪製流程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.