1. 程式人生 > >View的工作原理之Measure過程原始碼學習(一)

View的工作原理之Measure過程原始碼學習(一)

       在Android開發過程中,View控制元件的使用是最基本的技能,而自定義View技能的掌握也是非常重要的。這篇博文講記錄一下在讀任玉剛老師的《Android開發藝術探索》一書中學習到的相關知識以及自己的一些收穫。這裡說明一點,在"View的工作原理之Measure過程原始碼學習"系列文章中,原始碼都是基於android-26這一套原始碼。

       我們都知道,在開發android的過程中,只要在佈局檔案中新增我們需要的View,然後在Activity的onCreate方法中的setContentView中將佈局檔案載入進來就可以在啟動Activity之後,看到了我們新增的View。那麼這裡可以知道,View最後肯定是和Activity聯絡起來的,那麼他們之間的是怎麼聯絡起來的呢?通過原始碼發現,Activity和View之間是通過Window類的實現類PhoneWindow聯絡在一起的,每一個Activity擁有一個PhoneWindow的物件,而這些物件都通過WindowManager來管理,同時WindowManager也會為對應的PhoneWindow物件新增一個ViewRoot實現類ViewRootImpl的例項。ViewRootImpl例項就對應著Android的View檢視層次結構的頂部,從ViewRoot這個類名大概也可以看出,它是整個試圖的根,這一點有力的證據可以檢視ViewRootImpl類的註釋。

/**
 * The top of a view hierarchy, implementing the needed protocol between View
 * and the WindowManager.  This is for the most part an internal implementation
 * detail of {@link WindowManagerGlobal}.
 *
 * {@hide}
 */
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
       
}

        知道了Activity、PhoneWindow以及ViewRoot與View展示有關之後,這裡仍然需要了解一下DecorView。從上面可以看到ViewRootImpl並不是一個View,它不能夠承載View,這就需要用到DecorView了,DecorView是整個View檢視的頂級節點,也就是說,整個Android的View檢視是從DecorView這裡開始的,DecorView中包含兩部分,一個是ActionBar,這個設定根據主題變化。另一個是ContentParent,我們通過setContentView方法設定的佈局檔案,最終就會被設定到ContentParent中。下圖很好的展示了這幾個部分之間的關係。

      下面我想從Android應用程式的啟動過程開始,一直到Activity與PhoneWIndow的聯絡,ViewRootImpl與WindowManager的聯絡,ViewRootImpl與DecorView的聯絡過程,在原始碼中簡略的走一遍。

       上面的流程圖是我根據原始碼畫的一個程式執行方法路線圖,展示了Android應用程式的啟動過程,標註紅色字型1的路線是將Activity和PhoneWindow關聯起來的部分;標註紅色字型2的路線是DecorView的建立及將我們的View設定到DecorView;標註紅色字型3的路線是將DecorView和PhoneWindow以及ViewRootImpl關聯起來的部分。從上面的流程圖可以看到,在handleResumeActivity中,將DecorView通過ViewRootImpl的setView方法將DecorView關聯到View樹,即ViewRootImpl中的mView就是DecorView。在ViewRootImpl中有一個方法performTraversals,在這個方法中,DecorView進行了measure,layout,draw三個過程,分別對應performMeasure,performLayout和performDraw三個方法,如下圖所示。這裡只需要詳細瞭解performMeasure方法(是從哪個方法一路下來到達performMeasure方法,這個我還沒有找到)。

        在performMeasure方法中,會呼叫DecorView的measure方法,measure方法是final型別,所以最終呼叫的是View中的measure方法,而View中的measure方法會呼叫實現類的onMeasure中的方法,也就是DecorView的onMeasure,在這個方法中會呼叫super.onMeasure,DecorView繼承自FragmentLayout,FrameLayout繼承自ViewGroup,因為ViewGroup是抽象類,因此他沒有實現onMeasure方法,交由它的子類實現。所以最終會呼叫FrameLayout的onMeasure方法。在這個方法中,會迴圈遍歷子元素經行它們的measure過程(具體程式碼檢視FrameLayout的原始碼,這裡就不貼了)。