本文介绍 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 里控件的编写顺序不一致,只有当所有采用虚拟化控件搭建组件的时候,才不会出现这种状况。
讲得再多,不如亲自上手体验一下,能够参考这篇文章来体验。