【Android】解析SetContentView過程

開始前

上週在github上看到關於提高Android佈局加載速度的開源庫X2C。對於Android開發設置佈局不外乎於兩種方式:xml、Java編碼。過去有段時間我也嘗試着拋棄xml直接使用代碼去建立佈局,但問題在於代碼建立的佈局沒法實時查看、佈局過於複雜用代碼實現不太容易等缺點。X2C開源庫的功能大體上是經過編寫xml文件產出代碼文件,最終經過java代碼編寫UI佈局。java

兩種佈局實現方式的不一樣

雖然咱們日常在Android開發中經常適用xml文件編寫UI佈局,那爲什麼不使用易用可視化的xml佈局實現方式而採用代碼方式實現呢。其實xml方式的UI佈局多一層對xml文件的讀取和解析將xml文件中的各類UI控件最終實例化成Java代碼控件,因此最終仍是回到以Java代碼實現佈局的步驟,所以爲何說Java代碼實現佈局會比xml加載效率更高了,其大致上咱們能夠經過Android源碼探一探究竟。git

佈局加載方式

這裏主要拿Activity的佈局加載做爲例子。以前提到過佈局加載方法setContentView提供兩種方式提供xml文件的資源ID加載xml文件,另一種是View對象。
當前sdk版本中會根據BuildSdk版本不一樣建立不一樣的適配AppCompatDelegate對象,但這裏要講的建立佈局仍是在AppCompatDelegateImplV9中實現並未作重寫操做。UI佈局加載View對象的方式這裏很少加以解析,只是經過contentParent將須要呈現的UI佈局經過addView方法實現。下面仍是主要看看加載xml文件具體是如何實現加載佈局的。github

xml文件加載方式

xml文件是由LayoutInflater加載,LayoutInflater是一個抽象類經過from獲取context,而後方法inflate載入resId和contentParent。緩存

  • Resources

而後經過Resources對象的getLayout方法獲取到XmlResourceParser。getLayout經過loadXmlResourceParser加載layout資源,其中在ResourcesImpl獲得TypedValue,而後調用ResourcesImpl的loadXmlResourceParser判斷是從xml緩存區cachedXmlBlocks中獲得XmlResourceParser仍是從新建立XmlResourceParser結果。佈局

  • AssetManager

經過AssetManager的getResourceValue調用native層級loadResourceValue方法實例化TypedValue,若在Resources中未能找到當前佈局的xml緩存則經過native層級openXmlBlockAsset建立XmlBlock對象。XmlBlock調用newParser方法獲取到XmlResourceParser對象。ui

  • LayoutInflater

獲取到XmlResourceParser以後調用inflate方法。其中關鍵建立佈局DOM代碼在rInflate方法,方法內部while循環以及遞歸操做。除去上層邏輯判斷異常處理部分代碼後,重心關注最後View的建立和佈局拼接組合。經過createViewFromTag建立View對象而後經過addView將實例化的佈局控件裝載到ViewGroup(Parent)。那建立View的過程是代碼片是經過好幾種方式找到正確的建立View方法而建立的,大體能夠分爲Factory二、Factory、privateFactory以及LayoutInflater的createView方法。就近原則先看看createView方法的代碼會發現View的建立是經過反射方式獲取View最終newInstance實例化。而以上Factory二、Factory、privateFactory方式也大同小異都是經過反射建立View。編碼

clipboard.png

圖1-xml加載佈局大體過程spa

最後

加載xml形式的setContentView內部經過反射建立佈局確實不比直接用代碼建立佈局來得高效。每種方式總會存在好與很差的狀況,選擇哪一種形式去實現最終仍是由開發者自行斟酌選擇最佳方案。最後除了原生方式實現佈局建立其實還存在其餘更多樣化的編寫佈局方式,例如:Mist、facebook的litho。據說litho加載佈局方式可能會更好更高效,但也待進一步證明和調研。3d

相關文章
相關標籤/搜索