作者:谢伟(韦圣)

在上一篇《淘特 Flutter 流畅度优化实践》中说到,虽然一期效果较为明显,但距离极致的用户体验仍有不小的差距。去年,淘特端架构联合业务团队共同发起“基础链路极致体验优化”的项目,目标在时长与流畅度方面获得极致体验,本文将为大家详细解析淘特 Flutter 流畅度优化实践二期部分。

优化效果

首先,我们简单回顾上一期优化后的效果, 在一期中,主要的优化措施集中在“业务最佳实践”,不需要改Engine、不需要造轮子,依然取得不错的优化效果。证明Flutter在面对复杂的业务场景时, 只要掌握好足够的实践经验,依然能保持较好的性能表现。

但随着淘特的优化进入深水区,源自对极致用户体验的追求及Native性能数据的赛跑,让我们开始快速从集团、业界吸收优秀前辈的经验并自我突破。最终,在完成了“Hummer引擎升级”、“自研ExternalImage图片库”、“自研FlowView高性能流式容器”等多项重点技术突破后,取得的二期成果如下:

注:流畅度随着业务迭代、测试口径的变化存在一定波动。以上数据来自:淘特4.14.0 双端慢滑测试口径(滑动速率参考下方录屏)

从体感录屏来看有两大提升:

  1. 流畅度再度提升,双端慢滑基本无卡顿
  2. 消灭iOS大卡顿问题

Android录屏对比(左边优化前、右边优化后)

查看视频请点击:淘特 Flutter 流畅度优化实践 · 二期

iOS录屏对比(左边优化前、右边优化后)

查看视频请点击:淘特 Flutter 流畅度优化实践 · 二期

优化过程中关键技术

引擎升级 Hummer

相信不少同学都听过Hummer引擎(UC Flutter定制引擎),得益于UC丰富的渲染性能优化经验及AliFlutter社区生态,淘特在充分调研后决定接入Hummer,但同时接入的过程中,淘特又与Hummer遇见了很多复杂场景需要解决的流畅度、加载耗时、内存等各方面的问题。

首先升级Hummer引擎带来的流畅度优化主要在以下4个方面,具体原理参考Hummer引擎介绍,本文侧重讲淘特实际解决的问题与解法,及升级的对比效果。

下面是引擎升级的最终效果:

淘特Android4.4.0基线

淘特iOS4.6.0基线

双端在帧率、卡顿率都有了明显的提升,尤其是iOS端解决了Feeds流在iPhone6下容易大卡顿的问题。而升级引擎对淘特影响最大的就是外接图片库的升级。

Flutter图片库对比

以流畅度为例, 图片库的选择是至关重要的。由于Hummer引擎中迁移原有CDNImage(旧引擎耦合Engine的外接图片库方案)的成本过大,这迫使淘特寻找新的“非侵入引擎的图片库方案”。

最开始我们尝试用NetworkImage拿到了第一手的体验数据。流畅度提升非常明显,但NetworkImage的不足只能满足短期快速灰度,此时FImage(外接纹理的图片库方案)出现在我们面前,无疑是一个非常高效的解决方案,但实测后发现低端机流畅度较之前略有下滑,这让我们开始探寻更适合淘特的图片库方案。

最终自研ExternalImage, 在流畅度和加载耗时对比中均取得超越CDNImage的效果。

以下是集团Flutter主要的图片库方案对比:

以下为Hummer下ExternalImage与外接纹理方案帧耗时性能图,我们发现外接纹理方案的Raster线程帧耗时会显著高于原生Image组件方案,原因初步分析是过多的Texture使低端机Raster耗时负载过大, 而由于frame_time近似等于max(ui,raster), 所以当raster帧耗时超越16ms也会造成实际体感FPS的降低。于是就有了下一节的ExternalImage图片库。

淘特ExternalImage图片库

上面是一张ExternalImage的总体架构图, 其基于FFI方式加载来自Native的像素数据,从官方Image组件出发,经Provider发起Channel调用,拿到图片返回结果后触发decode、setState等流程, 绿色代表请求链路,黄色代表回传链路。

核心技术点如下:

淘特Flow-View轻量级流式容器

列表滚动一直是Flutter流畅度优化的重点场景,在未获得Hummer引擎优化前, 流畅度优化一度遇到瓶颈。在Flutter官方流式容器设计理念中,在列表滚动时, Element被视为非常轻量级的组件,没有支持复用。在列表增减元素时,Widget被认为非常轻量, 未做局部刷新。这在淘特实际复杂的Feeds业务场景下,受到了严峻挑战。我们结合业务特性,自研了一套轻量级流式容器方案Flow-View。 主要支持2个特性:

  1. 局部刷新, 将使分页加载更多无需重复build已有的itemWidget;
  2. Element/RenderObject复用, 将使滚动插入新元素时效率更高。

1、FlowView局部刷新

我们首先看上图右侧示意图,在局部刷新场景下,左边未优化前添加新元素将setState触发整个列表Rebuild。右边优化后将只对新增的2个元素执行插入操作,已有的元素无需Rebuild。

左侧为源码细节,通过在SliverMultiBoxAdaptorElement.update方法中,通过滚动到底部,且newDelegate.childCount>oldDelegate判断为加载更多场景执行局部刷新(即插入新的元素)。

2、FlowView Element、RenderObject复用

同样先看上图右侧示意图,在滚动场景下,当新的元素12、13即将入屏时, 左边未优化前将创建全新的Element、RenderObject。右边优化后新元素12、13将复用顶部移出的0、1元素的Element、RenderObject。做到循环利用,效率更高。

左侧为源码细节,当获取新插入的item时,通过在SliverMultiBoxAdaptorElement.createChild方法中,未优化前_childElements[index]=null将触发Element、RenderObjec新建,优化后将先根据新元素的类型找是否有可复用的元素,再触发updateChild, 若缓存不为空,则会执行didUpdateWidget逻辑。

当移除元素时,removeChild将不再deactive Element(即不触发updateChild)。同时通过修改framework将RenderObject从ContainerRenderObjectMixin双向链表中移除(renderObject._removeFromChildList)。再将Element添加进cacheMap即可。

Android滑动手感

在淘特,不仅关注流畅度数据的提升,更关注用户实际的体感。在某一次版本升级后,Android的手感不如以前顺滑,滑动初期阻尼感升高明显。如下视频对比。

1.优化前4.2.0

查看视频请点击:淘特 Flutter 流畅度优化实践 · 二期

2.优化后4.3.0

查看视频请点击:淘特 Flutter 流畅度优化实践 · 二期

分析原因是 基于BouncingScrollSimulation实现的下拉刷新组件改变了Android平台原有的Simulation。经过分析Android和iOS平台的Simulation滑动算法。

我们决定在Android上根据是否滚动到尽头时区分Simulation算法。在未滚动到底部前,我们仍然用ClampingScrollSimulation保持近似Android原生的手感,滚动到尽头后为支持下拉刷新,切换至ScrollSpringSimulation。基于此动态切换的算法封装了一个通用的BouncingableClampingScrollSimulation供业务使用。

总结与展望

综上,在一期、二期的优化中,淘特Flutter流畅度优化在线下测试中取得了不错的效果,部分页面超过了Native。低端机也稳定在较高的帧率。但线上用户的真实场景远比线下复杂的多,所以淘特将在今年对以下三个方面做加大投入。

  1. 从线下走向线上,参与AliFlutter-APM共建、建设淘特全链路性能分析平台。
  2. 在机型方面,淘特在从之前重点关注的低端机体验优化走向全机型的体验优化,这块计划在如滑动插值器卡顿调优、 适配iphone高刷屏、升级FlutterImageView/SurfaceTexture发力。
  3. 最后, 之前的优化工作很大一部分是人工专项优化,后续将做到更多流程自动化,如在低性能Widget告警工具、集成性能卡口工具等方面发力, 保障业务高质量低成本保持优化成果。

【参考文献】

[1]:Google Flutter 团队 Xiao Yu:Flutter Performance Profiling and Theory:https://files.flutter-io.cn/events/gdd2018/Profiling_your_Flutter_Apps.pdf

[2]:闲鱼 云从:他把闲鱼APP长列表流畅度翻了倍:https://mp.weixin.qq.com/s/dlOQ3Hw_U3CFQM91vcTGWQ

[3]:Google Android RecyclerView.ViewHolder:RecyclerView.Adapter#onCreateViewHolder:https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.Adapter#onCreateViewHolder(android.view.ViewGroup,%20int)

[4]: Jank卡顿及stutter卡顿率说明:https://perfdog.qq.com/article_detail?id=10162&issue_id=0&plat_id=1

[5]: 淘特 Flutter 流畅度优化实践

淘特 Flutter 流畅度优化实践 · 二期相关推荐

  1. 淘特 Flutter 流畅度优化实践

    作者:谢伟(韦圣) 不同的业务背景引出不同的技术诉求,"用户体验特爽"是淘特的不懈追求,本文将介绍笔者加入淘特以来在Flutter流畅度方面的诸多优化实践,这些优化不涉及Engin ...

  2. Flutter 流畅度优化实践总结

    本篇内容来自ArchSummit会议分享 作者介绍: 张云龙(云从),闲鱼客户端专家.先后在网易.字节.阿里任职移动端研发.目前在阿里巴巴闲鱼技术部,目前负责闲鱼 app 包大小.流畅度.启动等端体验 ...

  3. 已开源!Flutter 流畅度优化组件 Keframe | 开发者说·DTalk

    本文原作者: Nayuta,原文发布于: 进击的 Flutter 列表流畅度优化 这是一个通用的流畅度优化方案,通过分帧渲染优化由构建导致的卡顿,例如页面切换或者复杂列表快速滚动的场景. 代码中 ex ...

  4. 已开源!Flutter 流畅度优化组件 keframe

    列表流畅度优化 这是一个通用的流畅度优化方案,通过分帧渲染优化由构建导致的卡顿,例如页面切换或者复杂列表快速滚动的场景. 代码中 example 运行在 VIVO X23(骁龙 660),在相同的滚动 ...

  5. 已开源!Flutter 基于分帧渲染的流畅度优化组件 Keframe

    大家好,这里是承香墨影! 今天给大家推荐一个,Flutter 中利用分帧渲染优化流程度的开源库,刚开源,还热乎着.这次开源可真波折,看着 @Nayuta 前前后后在公司内部流程走了一个多月吧,太艰难了 ...

  6. 干货 | 从47%到80%,携程酒店APP流畅度提升实践

    作者简介 Jin,携程高级研发经理,专注移动技术开发:Dan,携程测试开发经理,关注数据挖掘以及数据在系统质量提升中的应用:Lanbo,携程软件技术专家,专注移动技术开发. 一.背景 APP性能提升一 ...

  7. 淘宝商品库MySQL优化实践的学习

    淘宝商品库MySQL优化实践的学习 淘宝商品库是淘宝网最核心的数据库之一,采用MySQL主备集群的架构,特点是数据量大且增长速度快,读多写少,对安全性要求高,并发请求高.由于MySQL最初的设计不是用 ...

  8. Android性能优化——界面流畅度优化

    Android性能优化--界面流畅度优化 序言 首先流畅度不仅仅是受到代码的影响.也会跟机器的硬件配置有关系.所以第一点需要明确的是,流畅度最低保证在哪个硬件配置之上.这样有了一个基点之后,才能比较好 ...

  9. Android App界面和流畅度优化

    Android App界面和流畅度优化 所谓界面和流畅度优化,就是尽可能多地消除用户可直接感知的.影响用户操作体验的bug 1.人为在UI线程中做轻微耗时操作,导致UI线程卡顿 人为避免一切耗时操作 ...

最新文章

  1. python 解析xml格式_Python解析XML文件
  2. 浅析C++中的this指针 通过空指针(NULL)可以正确调用一些类的成员函数?
  3. 信号处理:单边、双边频谱间的相互转换(转)
  4. word双引号间距大_微软判定:Word 编辑英文句号后“两个空格”为拼写异常
  5. linux 用户创建,权限,分组
  6. 模拟任务调度算法 C语言 【留学生作业】
  7. TOPSIS法 —— python
  8. 读取头部姿态数据集300W_LP、AFLW2000、BIWI数据集中的真值
  9. 使用接口实现打印机功能
  10. cas虚拟服务器,适用于CAS虚拟化平台的CloudOS3.0云主机镜像的制作
  11. 利用python的爬虫技术爬取百度贴吧的帖子
  12. 手写数字识别及python实现
  13. Win11系统白名单列表如何添加软件
  14. 南卡315打假!揭露山寨耳机“十宗罪”!
  15. 面试java项目中解决了什么问题,附源代码
  16. Linux Mint(Ubuntu)上 安装 效率神器 utools
  17. HTML小游戏22 —— html5版疯狂光头强网页游戏(附完整源码)
  18. 1800个python词汇_基本 Python 词汇
  19. banner背景图固定不动HTML,11种banner背景处理方式,给设计加一点思路!
  20. python家乡美食与旅游景点导游推荐系统django源码介绍

热门文章

  1. Redis set命令详解
  2. 双一流高校同寝室博士生连续三次打架,背后和科研压力大的环境密不可分
  3. 根据后端返回的文件流下载文件
  4. ShaderJoy —— 仿抖音 “天使光芒” 特效【GLSL】
  5. DevExpress报表的数据绑定及打印
  6. 云盘满足校园存储与数据共享
  7. 文章风格: 一级标题使用蓝色字体,二级和三级使用黑色,重点部分使用红色或黄色标记,正文采用浅灰色
  8. 技巧!笔记本电脑wifi图标无线不显示?连接不上?一招解决wifi网络问题------小白电脑的那些事
  9. 《ffmpeg入门学习》 六 java把多个图片合成视频,并添加图片水印
  10. ESP8266 Arduino 解决开发板管理器下载开发包失败和速度慢的方法