最近几年,移动互联网的发展日新月异,各种新技术就像雨后春笋般出现在我们眼前。这促使我们不断的去学习吸收,紧追移动互联网的浪潮。在这里,我们为大家分享下京东上海移动端团队在动态化方案上的一些探索历程和实践经验。前言随着原生业务的不断增加,各端需要不断投入人力进行开发、迭代,尤其在6.18,11.11等电商大促需求爆发期,人力愈发捉襟见肘。而且原生客户端的包大小会随着业务的增加而不断增大,对于客户端存在包大小限制而导致一些低权重业务不断下线,转为H5或RN实现;与此同时,需求方对用户的体验也要求较高,不接受体验降级的情况屡有发生。另外,原生开发需要跟版,导致业务上线周期较长的问题也急需解决。综合以上因素考虑,在2018年年底我们开始着手调研如何能让业务上线不依赖于发版,能够在多平台快速动态上线,最大限度的接近原生体验,降低各端人力的不断投入,遏制包大小过快的增长。我们带着这一系列问题,开始了逐步的探索、调研以及整个客户端框架上的一个构思。并与项目、产品、前端、后端进行合作,追求样式灵活拼装、数据动态绑定、渲染高性能的目标。设计思路本章节主要从「为什么要自定义语言协议」、「控件」、「模板是什么」、「解析“三步走”流程」、「整体看积木的完整流程」几个方面来介绍。01为什么要自定义语言协议首先我们要做一个能够满足以下三点的框架:



- 跨平台:同时支持iOS,Android和H5三端。
- 动态发布:发布活动不需要更新客户端版本,通过可视化界面拖拽和后台数据进行绑定,三端可以直接获取页面数据并显示。
- 低成本:发布或修改页面,可使用可视化平台配置样式和绑定数据,无须开发介入。

相关服务:泰国服务器
- 控件:表示控件种类,用于抽象对应虚拟树节点。
- 布局:表示控件布局的方式。例如:绝对布局、线性布局、弹性布局等。
- 样式:表示控件样式,确定当前控件对应坐标、背景色、边框、字体颜色、字体大小等。
- 事件:表示当前控件绑定的事件,单击、双击、长按等。
- 寻址:表示控件关联的数据,为了样式和数据的分离,通过寻址的方式建立控件和数据的连接,以及对应的数据占位逻辑也会在该属性去体现,寻址后的数据传递规则会根据具体的控件类型来确定。




- 业务层:该层次是对外沟通的一个媒介,可以根据当前页面的业务形式替换相应的控件,实现一系列接口便于处理埋点、统一跳转、网络请求、图片下载等事件(接入方APP对接viewkit SDK的时候,注册进来对应的回调组件,当有相应的事件触发的时候分发到对应的回调组件去处理)。
- 逻辑层:提供注册组件管理、模板处理、生命周期触发、复用、版本管理降级、网络和图片的统一处理等,通过以上管理模块,可以做到样式和楼层的复用,模板的增删改查操作,视图的初始化、销毁等,数据的寻址。
- 抽象层:DSL和数据分别分发到模板管理和数据层管理之后,开始虚拟抽象,通过数据寻址找到对应的模板,之后逐层递归扫描生成布局、容器、视图和元素控件,并通过寻址找到数据,解析绑定,进而抽象生成虚拟树。
- 显示层:主要对虚拟树内的结点进行压缩合并,虚拟对象转换成实体控件,创建生成图层,和整个视图的复用更新服务。


- 虚拟抽象层通过模板标示符获取模板时,首先通过模板标示符到内存中查找对应的模板,如果找到则直接返回,找不到则去本地模板库去查找。
- 本地模板库会初始化一些常用的模板和控件等,当运行内存中没有找到就到本地库去查找,找到后和版本做对比,如果匹配则返回模板,并保存在内存中,方便下次再次获取该模板,如果模板没有找到或者没有匹配版本,则去服务器拉取,成功则本地库保存,然后输出模板,否则直接返回错误。
- 为了防止内存过快的增长,我们制定了一套垃圾回收规则(当接收到内存不足、程序进入后台、程序关闭的通知时,我们会把缓存都清除掉)。

- 首先我们对事件结构信息和对应的数据信息进行校验,不符合标准直接返回失败,此事件不再添加到对应的虚拟控件上。
- 如果校验成功,则对事件进行抽象生成虚拟事件,同时绑定到对应的虚拟控件上。
- 当遇到用户触发(点击、双击、长按等事件),则把对应的事件信息分发到业务层注册的组件上进行处理;如果需要进行页面更新则回调给积木SDK。
{ "pictureUrl": "http://img.360buyimg.com/455be9563d43b606.jpg", "skuName": "精选纯棉好货女装短袖T恤女韩版宽松新款夏季女装半袖上衣", "price": "29.90"}在可视化平台需要将二者映射关系配置说明,由后台将业务数据进行加工,得到前端展示所需要的数据。映射关系如下: 
{ "image1": "http://img.360buyimg.com/455be9563d43b606.jpg", "text1": "精选纯棉好货女装短袖T恤女韩版宽松新款夏季女装半袖上衣", "text2": "29.90"}04如何优化性能- 高复用:大部分跨平台技术方案拥有动态性、研发效率、多端一致性等优势,但是性能方面都会比原生要差些,所以往往跨平台技术的性能优劣便成为核心指标。在不同的iOS和Android设备上,要显示成千上万个楼层和区域视图,如果不停的创建则生成千上万个对应的视图对象,内存很快会被耗尽,要想保证在有限的内存上高效的运行,就是最大限度的去复用。我们分别从楼层、DSL几个维度去做复用,页面内的楼层复用则采用楼层级别的复用池去公用不在当前页面显示的楼层,如果通过DSL生成的视图,就用DSL复用管理类依照页面复用的原理去管理DSL公用视图,这样就能做到区域视图的复用,当需要获取视图进行页面显示时,将虚拟视图传入到复用池中,复用池根据虚拟视图中的标识符判断内存缓存中是否有该视图,有则直接返回视图,无则创建视图,传入内存缓存,然后返回视图,对视图复用池的内存缓存采用垃圾回收机制,当超过设置的触发临界点(内存缓存大小超过设置值),则进行视图的释放操作,需要移除的视图用LRU和LFU算法综合进行判断。(LRU算法:最近最少使用算法,使用时间距离现在最久的那个被移除。LFU算法:最不常用算法,一定时间段内使用【次数(频率)】最少的那个被移除。)

降流量:通过DSL和数据解耦,能够更大程度的去复用公用的DSL,避免重复的样式下发,减小用户流量的损耗,缩短了从下载数据、解析、渲染、页面呈现给用户的时间。
- 优化节点:现阶段,积木的样式是通过拖拽和配置产生的,因为视图可以嵌套,会遇到嵌套层级过多的问题,为此,我们进行了相应的优化。我们在初始化视图阶段,将去除不影响显示的视图过滤(如设置了透明背景的View),减少视图的层级,从而减少了渲染时间和复用后重绘视图的时间。



文永军 资深研发工程师

黄 鑫 资深研发工程师

霍 坤 资深研发工程师

洪 鑫 资深研发工程师
文献资料链接- React Native:https://reactnative.cn/
- Flutter:https://flutterchina.club/
- jasonette:http://jasonette.com/
- weex:https://weex.apache.org/






