作者: Wison, 腾讯移动客户端开发 高级工程师
WeTest 导读
Pluto 是 iOS 上的一个排版渲染引擎, 通过 JSON/JS 文件可以很方便地描述界面元素, 开发效率很高, 并且在流畅度, 内存等方便有保证 pluto.oa.com 上有更多详细资料
Qzone Feed 业务复杂, 样式很多每次新增一种 Feed 样式, 开发工作量很大, 需要跟版本样式之间耦合严重, 每改一种样式, 另一种样式可能会受影响
基于这样的背景下, Feed Team 急需一个比较成熟的渲染引擎, 他至少需要解决以下问题:
1 提升开发效率
2 样式之间独立, 不互相耦合
3 新增和修改 Feed 样式不需要跟版本
4 无论采取什么方案, 列表的滑动流畅度必需保证至少跟现有的一样
基于这样的需求, 我们重新盘点了市面上比较成熟的排版渲染引擎 ComponentKit, 新的开发框架比如 React Native, 甚至参考 Android 的排版系统都难以同时解决上述问题, 最终决定我们自己来做一个, 一个专注性能和开发效率的排版引擎, Pluto 目前 Pluto 已经应用于 QQ,Qzone 上大部分的空间 Feed 样式, 关于 Pluto 和这些现有的排版渲染引擎对比的细节, 我后面会说明, 我们先来看看 Pluto 用起来是怎么样的
首先需要一个排版描述:
以上排版数据的结果如下, 左边是一个图片控件, 右边是文字控件
想必看到这个 demo, 大家应该知道 Pluto 是什么东西了上面的 JSON 文件阅读起来也非常自然, 直接接下来要解决的问题比较多这里重点描述点击事件模板重用扩展分别解决热更新, 开发效率, 性能优化功能扩充, 四个方面的问题
点击事件
Pluto 还可以通过 json 描述绑定事件响应的 js 脚本, 比如以下 json 文件:
图片组件被点击的时候, 可以找到相应的 js 文件, 调用 onClick 方法
模版
一开始的例子中, 使用一个 JSON 表达了一个 UI 排版, 假如有很多类似的界面元素同时存在, 就有很多重复数据的 JSON 文件这个时候就需要模版特性比如列表中的每个 Cell, 都共享同一个模版, 只是填充的数据不一样以下例子中, 将 imageName 替换成 ${image}, 而不是一个具体的图片然后提供一个字典映射, 每一个数据项映射不同的数据, 产生不同的视图
重用
重用是 Pluto 在设计之初就比较重点考虑的一个因素, 也是不同于其他引擎的最大的特色可以说有了这个特性, 才能应用在列表等有高性能要求的场景重用指的是, 在 UITableView 等列表控件, 在滑动的时候, 不同列表项复用同一个 Cell,Cell 里面的视图数据可以重复使用, 核心是为了减少创建视图和修改视图树的次数值得强调的是, Pluto 里面对视图的重用优化, 是已经内置的功能, 调用方不需要额外操作
实现原理如下图所示, 每个 Pluto 生成的视图中, 会包含一个复用池, 当使用复用特性时, 视图不会被销毁, 而是被回收, 回收时, 其子视图会被放入复用池内,(这里的子视图是一个视图树, 即也包含了子视图的子视图)并隐藏起来复用时, 就只需恢复显示, 调整宽高, 数据等, 比创建视图的成本低很多
扩展
Pluto 内置了一些渲染控件, 比如 文字 (TextItem), 图片(ImageItem), 按钮(ButtonItem) 如果这些组件不满足需求, 还可以通过扩展组件来完成封装实现自定义控件的大概流程如下:
在 demo 里面有演示, 包含了实现一个自定义视图的更多细节
特点分析
这里梳理一下 Pluto 的一些特点
快速: Pluto 的排版性能与直接书写的排版代码性能相差不大目前在手机 QQ 上跟其他列表相比, 流畅度领先(当然, 比 Auto Layout 性能好很多)
异步: Pluto 的整个排版, 文字渲染流程, 都是可以在工作线程执行的, 并且线程安全不会影响用户操作
描述型排版: Pluto 接收的排版信息是一个字典, 描述型的表达排版信息, 不需要写逻辑代码做成描述型的好处是:
方便维护, 不易出错(因为不包含代码)
方便缓存
可以是写成 JSON 格式, 通过本地读取, 或者后台下发来排版
不可变数据: 在整个排版引擎中, 排版数据是不可变的, 这意味着很容易维护测试缓存复用以及做到线程安全等等
缓存和复用: 由于排版数据是不可变的, 所以内部会进行缓存, 这样可以加快整个显示流程渲染部分则会尽量复用已存在的控件, 加快渲染同时同一个视图的排版数据更新, 也会内部做差异化对比, 排版流程中也会尽可能地复用旧的排版信息
模版体系: Pluto 有完整的模版功能同样的样式只需要书写一次, 形成模版, 然后根据情况往模版填充不同的数据, 可以生成不同的视图模版之间也可以通过组合来复用
图文混排: Pluto 支持基础控件的混排, 比如 Text 标签, Image 标签, 也支持自定义标签和自定义控件
对比分析
在对比分析之前, 我们先 review 一下 Pluto 的使用主场景: 一个可以无限加载更多 Feed 的 Feed 列表, 要求内存, CPU, 流畅度都有不错的表现
针对这个场景, 对比分析现有主流的界面开发库, 分别是 Xcode 自带的 Storyboard/Xib,Facebook 主导的开源组件 ReactNativeComponentKit, 以及本文的 Pluto
storyboard 是一个可视化的 UI 编辑工具, 开发效率比较高性能上, 控件都使用了原生控件, 所以性能会差一些也不支持异步排版, 影响流畅度生成的文件是使用 XML 描述, 理论上是可以动态下发, 但是 XML 格式不公开, 各个版本也不保证兼容, 所以比较难做到动态下发
React Native 使用 JS+html 的方式进行开发, 开发效率很高也有很高的动态性和跨平台特性但是性能比较捉急, 在速度上, 内存使用上有一些问题, 很难在 Feed 流这种性能要求比较高的地方
ComponentKit 跟 Pluto 其实很类似, 区别最大的地方在于 Component 不支持 JSON/XML 这种静态表达样式的功能, 以及事件动态绑定的功能在动态性和可维护性方面, 会弱很多我们有思考过在 ComponentKit 的基础上增加 JSON 表达样式的功能但是
ComponentKit 直接使用了原生视图, 并没有一个中间的虚拟视图层, 所以性能上也是问题改造成本太高
Pluto 相比 React Native 来说, 组件不够丰富, 使用 JSON 可以让开发效率在描述排版方面接近 React
Native; 性能相比其他组件来说很不错; 支持异步保证了主线程的流畅度; 动态性跟 React Native 一样, 不能新增控件, 控件都是本地预埋比较依赖本地代码的逻辑, 不能修改本地代码的已有逻辑, 但是可以替换一部分当然, 逻辑只能预埋的话, 也不会有审核风险
梳理表格如下:
腾讯 WeTest iOS 预审工具
为了提高 IEG 苹果审核通过率, 腾讯专门成立了苹果审核测试团队, 打造出 iOS 预审工具这款产品经过 1 年半的内部运营, 腾讯内部应用的 iOS 审核通过率从平均 35% 提升到 90%
现将腾讯内部产品的过审经验, 以线上工具的形式共享给各位在 WeTest 腾讯质量开放平台上可以在线使用点击 http://wetest.qq.com/product/ios 即可立即体验!
如果使用当中有任何疑问, 欢迎联系腾讯 WeTest 企业 QQ:800024531
来源: http://geek.csdn.net/news/detail/256353