爱奇艺页面动态化组件方案的演进
导读
一直以来,移动端应用都在不断寻求页面动态化解决方案
为什么需要动态化?
关于移动端应用需要动态化的原因,归结起来有:
快速的业务迭代:在当下的互联网行业,敏捷开发是主流的模式,小步快跑,快速迭代是常见的开发节奏,但是即使每周一次发版迭代(实际上多数应用达不到),某些功能的产品周期还是过长
应用市场审核:尤其是对于iOS应用,由于需要Apple的审核,正常情况下提交到用商店后,需要等待一段时间来审核
新版本用户升级慢:新版本发布后,更新覆盖到所有用户需要较长的时间
强运营需求:各种强运营需求,如A/B Test分区内容运营等也需要动态化的能力。
所以,对于主流大型移动端应用而言,动态化几乎可以认为是刚需,爱奇艺自然也不例外。本文就爱奇艺移动客户端团队在过去几年业务快速发展的过程中,页面动态化方面的实践和探索进行分享,共同进行交流讨论。
爱奇艺移动端的动态化大概经历了下面几个阶段:
1. 初步动态化,内部代号Card 1.0方案
2. 将行为与数据规范化统一的动态化,内部代号Card 2.0方案
3. 引入模板和样式的概念,将结构与样式分离,进一步将UI组件动态化。支持组件与样式复用,支持任意层次挂接事件,支持统一的事件处理框架和pingback框架,内部代号Card 3.0方案
4. 借鉴大前端的思想,引入布局描述的概念,舍弃自定义DSL,使用XML格式描述布局。排版方面,支持双层flex排版。事件逻辑方面,引入脚本语言,支持动态下发逻辑。 内部代号Card 4.0方案
整体演进脉络如下图所示:
下面分别就各个方案做介绍
Card 1.0方案:
该方案中,页面按照一定的规则拼接成json格式的数据,各字段按照功能类别划分成一些json节点,并构成层次关系,主要分为头部结构、内容结构、以及一些控制结构等。客户端请求后端得到数据后,对这些数据进行筛选、解析、拼接,并与UI控件进行绑定,最后显示到屏幕上。
Card 1.0方案较好地解决了数据动态组织的问题,并且支持了初步的显示控制。但也存在明显的不足之处,主要体现在:
1. 客户端需要筛选返回的数据,逻辑复杂
2. 客户端需要做很多拼接工作,并且没有规范化的处理方法
基于上述这些不足,我们很快发展了Card 2.0方案
Card 2.0方案:
Card 2.0方案可以看成是一套页面元素组织显示规范:整个页面切分为一系列称为card的组件,card组件作为前后端复用组装的基本单元。每个card组件由4个可以自由组合的部件构成,即标题栏(top_banner)、尾栏(bottom_banner)、分隔栏(gap)、内容区(container) ,如下图所示:
Card 2.0方案的优点是概念相对简单,UI结构清晰,客户端实现高效,其很好地满足了一段时期内的动态化需求。但是随着业务的不断扩展,特别是功能和交互的复杂化,也逐步暴露了一些问题,如:
card种类膨胀:以整个card作为组件复用的单元,复用的粒度过大,导致实际复用率不高,随着业务的扩展,card种类不断增多,直接导致了包大小膨胀的问题
动态化不够,具体体现在:
其一,不深入:动态化在协议层面只规定到card级别,对于内部元素与事件的动态化并无涉及,实际的实现方式随着业务和开发人员的不同,也各不相同
其二,不规范,只能两端约定使用自定义字段、语意等,case by case实现,没有统一规范化的做法
对多事件的支持不理想:由于Card 2.0协议的原始设计主要着眼于海报展示类
应用,对于事件的动态绑定设计比较简单,每个container item最初只能绑定一个事件,后期开发交互复杂的功能时,应对多事件的能力不足。
Card 3.0方案:
为了推进动态化方案的继续发展,在总结Card 2.0协议实施情况的基础上,我们着手设计Card 3.0方案,在项目启动之初,确定了Card 3.0的如下目标:
细粒度:
降低组件的粒度,最基本的复用组件从card减小为block
结构样式分离:
引入了card模板和样式表的概念,将结构与样式分离。其中card模板负责描述整个card的骨架信息,如定义每行block的数量及占比,分割线的显示等;样式数据负责描述控件的详细样式;card模板和样式表再结合页面数据,构建整个页面的UI结构。
灵活、复用:
card模板、样式表以及页面数据都支持动态投放
card模板和样式在多个card间复用
下面是一个应用Card3.0方案的页面UI结构简图:
其中
page:代表整个页面
card:逻辑分割单元,通常用来对不同的数据来源、不同的功能类别进行归组划分
block:基本的UI复用单元,表示一个相对稳定的UI组件,如图片+若干描述,播放器+描述等。通常建议按照UI组件的通用程度来进行拆分
control:封装的基本控件,主要有图片、按钮、简单文本、富文本、播放器等,支持业务层注册自己的控件
除了上述主要组件,还有seprator(横向分隔组件),gap(block之间的分隔组件)等,其样式(宽高、颜色等)都由样式表进行控制
Card 3.0协议的整体架构如下图所示:
card模板和样式表的动态更新:
card模板和样式表通过统一的接口进行更新。由于card模板和样式表的更新接口与页面数据接口是互相独立的,为了解决可能出现的数据不一致的问题,在请求页面数据时,将本地card模板和样式表的版本作为参数带到后端请求中,后端筛选与当前模板和样式兼容的页面数据,下发到客户端,整体过程如下图所示:
事件处理与级联:
在原始数据中,行为事件是由行为数据来描述的。行为数据描述了行为事件(点击、滑动、摇一摇等)发生后,所触发的行为和所需要的参数,行为数据关联到控件上,控件在触发所指定的行为时,框架会执行相应的事件。
为了统一处理同一控件在不同事件之间,样式和行为的切换,设计了事件级联协议。大致的思路是,下发多个控件样式描述及跳转路由表,抽象所有行为数据对应的事件的执行结果,根据执行结果结合路由表决定事件和样式的切换路径。举个例子,如订阅按钮,其初始样式为“订阅”,其行为数据是执行订阅动作,对应一种UI样式,如果订阅成功,其行为数据应该切换为“查看更新”,并对应于另一种UI样式;如果订阅失败,其遵循另一条切换路径。通过事件级联协议,上述过程完全可以统一自动处理。级联事件的原理如下图所示:
Card3.0是目前爱奇艺移动客户端主力动态化方案,应用非常广泛,大部分基线频道页面都应用了该协议。
Card 4.0方案
一方面,随着大前端概念的兴起,越来越多Web概念被引入到移动开发领域,如RN和Weex,Web前端的一些概念和工具确实能在某些方面提高开发效率,值得传统移动客户端开发人员思考和借鉴;另一方面,随着Card 3.0方案在爱奇艺移动端双平台(iOS、Android)各业务的大规模落地,逐步暴露了一些需要改进的地方,主要体现在:
1. 自定义DSL学习成本高,应用范围较为狭窄,小规模团队内部使用问题不大,但是当大规模推广到其他团队时,会面临学习成本高,需要反复培训的问题
2. 随着落地页面的增多和样式交互的复杂化,样式配置也越来越复杂,在多个团队同时使用时容易冲突,即使配套开发了样式管理平台,还是只能在一定程度上缓解该问题。
3. 落地形式以完整页面为单位,不支持与原方案混排,侵入性大
4. 对后端数据协议依赖性高,对其他数据结构的适应性差
5. 不能动态下发逻辑
基于上述情况,在上一代方案的基础上,我们进一步发展了Card 4.0方案,相对以前方案,有如下特点:
1. 通过XML格式的布局文件描述组件单元,由解析器负责解析创建
2. 排版遵循flex描述,舍弃了之前维护成本很高的自定义模板
3. 组件单元的组合使用了基于flex规则定义的layout pattern协议
4. 组件解析生成后进入自定义复用池,支持多种复用模式,高效复用
5. 支持业务层注册自定义Tag组件
6. 支持业务层注册自定义属性
7. 支持样式预解析及异步排版,提高解析排版效率
8. 支持多种落地方式,如Card页面、Card混排、Block混排、结构化非Card列表,独立UI组件等,方便以多种形式与原有业务结合,侵入性低
9. 业务逻辑引入Lua/JS脚本,支持一定范围内动态下发逻辑
Card 4.0的整体架构如下图所示:
其中Skin Designer是为了方便布局文件生成而开发的一个工具,支持通过拖拉拽的方式生成布局文件;
Hot Swap是热更新模块,动态更新布局和脚本资源
目前Card 4.0方案已经落地到爱奇艺移动客户端多个线上业务,如儿童频道、VIP频道、钱包模块等,其学习成本、开发效率、性能表现均优于上一代方案,目前正在更多业务铺开。
总结
纵观card方案演化的整个过程,不难发现一直是按照下面的规律来进化的:
粒度的不断细化,从整个card组件,到block组件,再到基本的原子控件
描述的规范化,从自定义DSL到通用描述形式(XML布局文件,flex排版
某种程度上脚本也可以看作是一种规范化的配置文件)
动态化,将静态特性转化为动态化配置进而脚本化,动态化能力不断增强
目前Card 1.0协议已经完全退出;Card 2.0协议存在少量遗留页面,即将完全退出;从业务占比上看,Card 3.0协议是目前的主力,但是正在被Card 4.0协议逐步替代。
上述过程是一个业务驱动的过程,同时也是一个技术驱动的过程,几个方案在不断演化的同时,支撑了近几年爱奇艺移动端大多数业务的发展。
需要指出的是,本文主要讨论的是方案的客户端部分,移动后端团队为方案的快速高效落地也做了大量的工作,提供了很多方便的工具,如模板系统、自助式样式配置系统,支持预览的Card配置平台等。
后续规划
一方面,将进一步扩大Card 4.0方案的应用范围,通过更多业务的迭代推动方案的完善与成熟;
另一方面,将完善相关的工具,如布局生成器、支持布局、样式hot reload的调试器等。
此外,在完成文档和样例建设后,Card 4.0方案会逐步开源,敬请期待。