本文介紹 VirtualView 方案裏虛擬化控件的原理,包括尺寸計算與佈局的實現,以及它與原生控件組合使用時的邏輯交互。html
VirtualView:若是還不清楚,能夠閱讀《天貓客戶端組件動態化的方案——VirtualView 上手體驗》大概瞭解下;android
原生控件:就是經過封裝了系統原生 View 來實現的控件;git
虛擬化控件:使用 canvas 繪製建立的控件,它須要依託一個原生容器控件做爲宿主容器,承重其最終的展現;github
先了解一下內置的控件組織關係:canvas
IView
定義協議接口,包括三個過程:佈局
系統渲染組件的時候分別會調用這幾個過程。ViewBase
定義控件的基礎屬性;虛擬控件都繼承自 VirtualViewBase
,虛擬容器控件都繼承自 Layout
,原生控件須要按照本 IView
的協議進行封裝,這個封裝成就是須要繼承自 NativeViewBase
;這樣虛擬組件和原生組件都有共同的對外接口,當系統渲染的時候不論虛擬化控件仍是原生控件均可以用通用的方式調用,爲混合方式搭建業務組件提供了可能性。.net
經過在宿主容器裏,掛了一個虛擬容器控件、一個虛擬文本控件、兩個原生圖片控件,能夠組合成一個複雜的業務場景下的組件,當它被最終渲染出來的時候,系統只看到宿主容器和連個原生圖片組件,並且系統看到的是宿主容器下直接掛載了圖片控件;若是按照常規的方法開發,這種佈局結構,系統就看到了宿主容器、一層佈局、一個文本、兩個圖片,並且總共有 3 層結構,因此本方案能經過視圖結構扁平化、虛實結合的方式搭建視圖。設計
當這樣一個 VirtualView 掛載到系統佈局容器裏的時候,系統就要對他進行測量、佈局、繪製三個階段,才能顯示出來。而這三個階段觸發的入口即是宿主容器的 onMeasure
,onLayout
,onDraw
三個階段。對於從 XML 里加載出來的整個組件來講,會構造一棵 ViewBase 樹掛載到宿主容器裏,在宿主容器的 onMeasure
,onLayout
,onDraw
三個階段裏調用 ViewBase 樹根節點的 onComMeasure
,onComLayout
,onComDraw
,而後再進一步遞歸調用子節點的這些方法,就配合系統顯示流程完成了對應的邏輯。虛擬化控件的尺寸計算協議與 Android 系統的協議一致。對於原生控件來講,IView
的實現就是調用 View
的對應方法,而對於虛擬化控件來講,onComMeasure
過程與實現自定義 View
同樣完成計算邏輯,而 onComLayout
過程須要根據計算結果控制子節點的佈局位置或者繪製位置,而 onComDraw
階段就是操做 canvas 對象,偏移必定位置,而後開始繪製。code
上圖實例中,圖標都是原生控件,而標題都是虛擬控件。cdn
如上所述,虛擬化控件的展現實際上是依賴於一個宿主容器 View,那麼對於全部虛擬化控件來講,最終都是繪製到同一個宿主容器上的,宿主容器的繪製層級老是在最底層,所以當虛實結合使用的時候,原生控件會擋住虛擬化控件,所以實際的顯示順序會和 XML 裏控件的編寫順序不一致,只有當所有采用虛擬化控件搭建組件的時候,纔不會出現這種狀況。
講得再多,不如親自上手體驗一下,能夠參考這篇文章來體驗。