天天看點

Android裡應用程式,應用程式視窗和視圖對象之間的關系

    很久沒更新部落格了,在新部落格裡打算對android的view的繪制機制進行全方位分析,由于涉及到的範圍相當之廣(比消息機制裡涉及到的還多,簡直可怕),是以打算先來個總序來說清楚應用程式(activity),應用程式視窗(window)和視圖對象(view)之間的關系,友善讀者對接下來的部落格(view的繪制)能更好地了解,這就是這篇部落格的目的。

   在Android裡, 每一個Activity元件都有一個關聯的Window對象,用來描述一個應用程式視窗。每一個應用程式視窗内部又包含有一個View對象,用來描述應用程式視窗的視圖。應用程式視窗視圖是真正用來實作UI内容和布局的,也就是說,每一個Activity元件的UI内容和布局都是通過與其所關聯的一個Window對象的内部的一個View對象來實作的。

  先來張圖理一下(從其他部落格裡盜用的圖):

Android裡應用程式,應用程式視窗和視圖對象之間的關系

 對于window,DecorView,view,viewGroup,windowMnager和viewRoot的關系如下:

   1.每個主視窗中都有一個view,稱之為decorview,是主視窗中的頂級view,實際上是viewGroup,viewGroup又是對一組view的管理,是以在viewGroup中建立了所有view的關系網,那麼是如何實作的呢?是因為在view中有兩個成員變量叫做mParent,mChildren,它們就是用來管理view的上下級關系的。而最終viewGroup附屬在主視窗上,這樣就很容易實作在視窗中通過findViewById找到具體的view了。當然,view的事件處理也是根據這個路徑來處理的。

   2.windowManager主要是用來管理視窗的一些狀态,屬性,view增加,删除,更新,視窗順序,消息收集和處理等等。windowManager繼承自ViewManager.裡面涉及到視窗管理的三個重要的方法,分别是:addView(),updateViewLayout(),removeView(),在windowManager中還有一個靜态類layoutParams,通過它可以設定和獲得目前視窗的一些屬性。首先來看看addView()方法,在該方法中,會利用layoutParams來獲得window中的view的一些屬性,并為每個window建立viewRoot,viewRoot是view和windowManager之間的橋梁,真正把view傳遞給windowManager的是通過viewRoot來實作的(setView()方法)

  3.ViewRoot相當于是MVC模型中的Controller.實際上,ViewRoot繼承自handler,是以也實作了view和windowManager之間的消息傳遞,視窗中的view的事件處理,消息發送,回調事件等都将通過ViewRoot來處理。

   4.當activity對象被建立完畢之後,會在PhoneWindow中生成一個DecorView,DecorView是一個視窗的頂級容器,其本質是一個FrameLayout,同時會建立ViewRootImpl(ViewRoot的實作類)對象,并将ViewRootImpl與DecorView建立關聯:

public void reportActivityRelaunched() {
        if (mDecor != null && mDecor.getViewRootImpl() != null) {
            mDecor.getViewRootImpl().reportActivityRelaunched();
        }
    }
           

  View 的繪制流程從 ViewRoot 的 performTraversals 方法開始,經過 measure 、 layout 、 draw 三大過程完成對一個 View 的繪制工作。 peformTraversal 方法内部會調用 peformMeasure 、 peformLayout 、 peformDraw 這三個方法,這三個方法内部又分别調用 view 的 Measure 、 Layout 、 Draw 方法。