美团 iOS 端开源框架 Graver 在动态化上的探索与实践( 四 )


  • 绘制结点:渲染结点树中的结点如果可以转化成绘制结点树中的结点 , 则称之为绘制结点 , 最后通过 Graver 进行渲染 。
  • 原生结点:渲染结点树中的结点如果不能转化成绘制结点树中的结点 , 只能转化成系统 UI 控件则称之为原生结点 。
  • 结点变异:以一个二叉渲染结点树为例 , 左子结点是原生结点 , 右子结点是绘制结点的情况下 , 由于左子结点先于右子结点添加到父节点 , 可能存在层级颠倒问题 。这时右子结点需要强制转为原生结点 , 维持正确的层级顺序 , 即结点变异 。
  • 画板视图:继承自 UIView 的普通视图 , 其内部封装了一系列的基于 Graver 的渲染逻辑 。
树拆分的过程还涉及到兄弟结点层级颠倒以及布局交叉等问题 。兄弟结点层级颠倒问题通过结点变异来解决 。布局交叉问题存在于判定渲染结点树的结点是绘制结点或原生结点之前 , 由于布局原因存在视图交叉 。布局交叉问题通过新建画板视图插入来保证层级正确以及绘制正确 。由于篇幅有限 , 这里不再赘述 。
3. 极端场景下的绘制效率瓶颈问题
从产品交互层面看 , 为了提高屏效往往存在多向滑动的视图组件场景 。如横滑 Scroll 组件 , 其特点是需要通过滑动才能逐渐看到所有的视图内容 。通过异步渲染绘制位图来实现的情况下 , 存在单一并发渲染任务计算逻辑繁重的问题 , 从用户体验层面看容易造成“白屏”现象 。为解决该问题 , 将视图卡片渲染过程分解 , 进行增量渲染 , 采用渐进式的方式减少空白页面等待时间 。根据待展示区域在屏幕中相对位置进行区块划分 , 通过队列集中控制绘制操作 。以此进一步提高并发效率 , 并减少渲染过程的非必要系统资源消耗 。
区块划分
区块划分策略的实质是绘制结点树的拆分 , 将绘制结点树中不存在布局交叉的子结点树进行逐一拆分 , 每个拆分下来的绘制结点子树即为一个区块 , 同时要设置最小块策略 , 否则拆分粒度太小反而会因为过多的线程并发造成性能瓶颈 。
美团 iOS 端开源框架 Graver 在动态化上的探索与实践

文章插图
 
图13 分块
分块绘制
以下图为例说明分块绘制逻辑 。在滑动过程中 , 若本地缓存有此区域绘制结果 , 读取缓存并直接通知主线程展示 , 如例4中 X4' 。否则 , 将该区域加入队列 , 以块为单元进行并发绘制 , 绘制完成后更新缓存 , 再通知主线程展示 , 如例1中 X1’ , 例2中 X2‘ , 例3中 X3’ 。对划到屏幕外的区域 , 从队列中清除 , 终止绘制操作;若此区域已绘制完成 , 则通知主线程清除此区域的展示 , 如例2中 X2 , 例3中 X3 , 例4中 X4 。
美团 iOS 端开源框架 Graver 在动态化上的探索与实践

文章插图
 
图14 分块绘制示意图
业务应用
在完成“拼控件”到“画控件”的思路探索与技术落地之后 , 需要发挥其价值 , 将其部署到线上进行业务实践应用 。动态布局框架 MTFlexbox 的跨平台代码复用能力对业务开发效率有了大幅提升 。从产品层面看 , 在原有资源不变的情况下 , 达到了高效支撑业务迭代的效果 。MTFlexbox 动态布局框架在经历了一次联合共建的“洗礼”后渲染性能得到大幅提高 , 变得愈加成熟、完善 。在过去的半年多期间 , 我们采用异步渲染引擎 Graver 的 MTFlexbox 已先后应用在搜索结果页、美团首页等核心流量区业务 。下面列举部分应用案例:
美团 iOS 端开源框架 Graver 在动态化上的探索与实践

文章插图
 
图15 美团首页、搜索结果页
采用异步渲染引擎 Graver 的 MTFlexbox 绝大多数应用场景为列表级应用 。如上图所示 , 所有视图卡片均为采用 M-Graver 实现的动态模板 。截止到发稿 , 覆盖搜索结果页36个动态模板 , 覆盖首页42个动态模板 , 业务应用累计覆盖78个动态模板 。
数据指标
以业务应用美团 App 新版首页为例 , 分类频道卡片以下全部为 MTFlexbox 实现的动态模板视图卡片 。由于采用异步渲染引擎 Graver 的 MTFlexbox 具备了在线程安全条件下进行测量、布局、渲染 , 美团首页接入后滚动 FPS 提升明显 , 对于上拉加载过程的 FPS 提升更为明显 。因此 , 列表使用体验变动更加顺畅 。美团首页的50分位滚动 FPS 接近59 , 上拉加载 FPS 接近满帧 。详细数据如下图所示:


推荐阅读