UC Flutter技术实践分享

简介: UC于19年开始探索Flutter技术,并在同年年底进行规模化落地。规模化落地Flutter核心要解决的三类问题分别是工程构建体系的搭建,性能优化和动态性支持。本次分享将由阿里巴巴UC事业部无线开发专家刘森森为大家详细介绍UC在规模化落地Flutter过程中解决的问题,及其思考过程。

摘要:UC于19年开始探索Flutter技术,并在同年年底进行规模化落地。规模化落地Flutter核心要解决的三类问题分别是工程构建体系的搭建,性能优化和动态性支持。本次分享将由阿里巴巴UC事业部无线开发专家刘森森为大家详细介绍UC在规模化落地Flutter过程中解决的问题,及其思考过程。

演讲嘉宾简介:阿里巴巴UC事业部无线开发专家——刘森森(花名:森尼)。14年加入UC,长期在UC信息流团队负责信息流业务的技术工作,近一年投入到创新产品的研发中,负责Flutter技术在创新产品的应用与实践。
以下内容根据演讲视频http://mudu.tv/watch/5624777以及PPT整理而成。

本次分享主要围绕以下五个方面:

            一、Flutter在UC落地的情况  
            二、工程体系构建  
            三、性能优化  
            四、动态性探索  
            五、总结  

一、Flutter在UC落地的情况

业务落地情况

Flutter具备高性能、高效率两个特性。UC作为创新事业群的一部分,以创新为重要使命,希望Flutter可以直接加速UC的创新。目前UC国内有50%的研发同学已经使用Flutter。从前需要两端开发的需求现在一端人力就可以支撑,并且前端同学可以加入做Native需求的行列,研发效率得到大幅度提升。

目前UC有两类业务。一类是成熟业务,例如UC和夸克,其新功能会优先考虑使用Flutter。一类是创新业务,例如小萌圈和古桃,基本都使用Flutter开发UI。

屏幕快照 2020-06-22 下午3.09.15.png

夸克&UC具体业务形态

夸克&UC的业务形态是将Flutter嵌入Native框架,是混合栈开发模式。业务以feed流为主,内容以音视频、图片、GIF为主。

屏幕快照 2020-06-22 下午3.11.47.png

创新产品

90%页面使用Flutter开发。未来发展的方向即UI将尽可能使用Flutter进行开发。

屏幕快照 2020-06-22 下午3.12.55.png

总览

UC落地Flutter有多种场景,目前的阶段是将Flutter规模化落地到创新业务中,加速UC的创新发展。

当前UC的Flutter落地面临着以下三类问题。

工程构建体系:如何提高Flutter落地效率?
性能优化:UC业务痛点在哪里?
动态性探索:如何结合业务实现动态性?

二、工程构建体系

核心目标——高效率

可快速集成到现有APP。
可快速构建全新的Flutter应用。
研发可快速上手。

工程架构

将Flutter业务落地到UC中有两种方案。

集成到现有APP:Add Flutter to Existing APPs。目前UC使用的是Flutter Boot解决方案。Flutter Boot提供了两个核心优势。一,产物集成和源码集成可配置。UC中有部分同学是没有用到Flutter的,在开发中应该避免由于Flutter打包带来的效率损耗,所以希望面向该部分同学配置产物集成方式。面向flutter开发同学希望配置源码集成方式。以实现效率最大化。

二,Flutter Boot提供Native和Flutter开发两种视角。Native开发视角指在Native工程中执行Native的构建脚本、命令。官方方案只能使用Native开发,无法使用一些flutter tool的高效命令,会造成研发效率的下降。另外,前端同学更希望使用Flutter原生命令,而不希望理解安卓和iOS两种构建体系的差别,因此Flutter Boot对前端同学友好。

集成到Flutter APP:全新APP。推荐使用Flutter官方解决方案,更高效、简单。

工程架构:Flutter业务以Package依赖的工程结构组织。UC是多团队、多业务的开发模式,期望业务之间解耦。目前Flutter不支持产物分离,都打包在一起,因此前期希望在工程方面尽可能做到解耦。公共组件会放到UC pub中,pub管理比git管理更加高效直观。目前UC pub中沉淀了许多业务组件和技术组件。UC pub上游可进行修改。技术组件打磨成熟后可以回归Ali pub或pub dev。

屏幕快照 2020-06-22 下午3.14.08.png

业务架构

业务架构核心思路是抽象几个核心模块,构建架构模板,使业务开发同学有一致认知。

最下方使用Flutter Boost解决方案,Flutter Boost是开源比较久的混合栈的解决方案。UC是Flutter Boost的重度用户,同时积极反哺社区,例如支持hero动画等。即使UC使用了Flutter Boost,UC希望Flutter页面之间的相互跳转是使用原生方式,支持hero动画可以使动画做的更漂亮。

每个Package使用Flutter Redux,主要是因为Flutter Redux能够解决复杂场景的状态管理。另外许多前端同学拥有Redux开发经验,可以带领客户端同学学习。

屏幕快照 2020-06-22 下午3.15.38.png

UC通过上述业务架构约束,使研发认知一致聚焦,降低研发上手的成本。

分层架构

UC在业务层下面构建了容器。容器最底层包含端基础设施,有阿里巴巴集团和UC沉淀多年的移动组件。这些组件将被包装为Flutter基础组件提供给业务。Flutter基础组件、Flutter容器、端基础设施可以打造一致的API层提供给业务层去做接入。

好处是开发新APP时,一致的API层均可以复用。
根据分层架构可以做进一步思考,一致的API层能否更方便地进行业务迁移?例如UC正经部是在UC里做的,是能否将其方便地孵化为一个创新APP。UC正经部的功能是使用Package依赖,能否方便地将其提取出来放到其他APP中。这是一个比较理想化的实现,但其方向是可以研究的。

屏幕快照 2020-06-22 下午3.16.36.png

UC通过以上三种架构模板解决Flutter落地到业务的效率问题。后续会随着社区和业务的发展,进一步优化架构体系。

三、性能优化

核心目标——解决业务痛点

做业务高可用建设。
引擎启动速度优化。
视频外接纹理方案优化。
图片组件优化。

业务高可用

UC主要做了两件事。

指标体系:一是构建了一套指标体系,与Web和Native的指标模型一致。有以下指标项。

页面打开性能:页面首帧绘制、内容首帧、首屏可交互。

页面流畅度:平均帧率,卡顿帧率。

页面稳定性:白屏检测,异常收集,网络请求异常。
UC的高可用组件在闲鱼高可用基础上进行了升级,增加了一些指标,并支持原生Navigator。

itrace:二是将收集到的数据上传到了实时监控平台itrace上。itrace是UC使用了多年的实时监控平台服务。目前itrace对内、对外可接入。

对外: https://yueying.effirst.com
对内: https://yuque.antfin-inc.com/wpk/help/ppxlrg

itrace主要有以下优势。一,分钟级别的实时性。二,提供多维度的分析方式。三,支持聚合,快速定位top问题。四,可配置预警规则。

Flutter实时大盘:如下图所示(样例),以实时图表形式展现数据。

屏幕快照 2020-06-22 下午3.18.36.png

高可用——页面性能:页面打开流程如下。首先监听路由跳转,在路由起始时打一个起始点,然后监听每一帧的回调。第一帧回调视为首帧,打一个点,继续检测,直到图片、文字、视频等Render Object出现,打一个内容首帧。内容首帧贴近用户视角。继续检测直到组件覆盖度大于60%,打一个首屏可交互。

该逻辑中还添加了白屏检测,可从dart层检查是否有文字、视频、图片。

页面性能在itrace上的展示形态如下。将内容首帧、可交互时间全部展示出来。下方是其实时曲线。可以选择分钟级别、小时级别、天级别。每一个业务下可能有多个页面,可以具体查看每一个页面性能。

页面帧率使用handleBeginFrame和handleDrawFrame计算每一帧的耗时。通过算法可以计算出平均帧率与卡顿帧率。

屏幕快照 2020-06-22 下午3.19.30.png

目前页面性能仅支持UI Thread的监控。handleFrame方案是实时的,可在发生卡顿时还原一些现场。

高可用——维度分析:可以根据网络类型、运营商、平台、客户端、页面版本、地区等设置维度来查看。例如将WiFi设为筛选,就可以展示出WiFi下的性能。

屏幕快照 2020-06-22 下午3.20.17.png

高可用——异常收集:此处指Dart异常收集,不包括引擎的异常收集,引擎异常崩溃走Native高可用。Dart异常重可导致白屏,轻可导致局部白屏。

使用Dart提供的runZoned进行异常收集。使用HttpOverrides做网络接口的异常采集。

异常展现在itrace上,可以按照一定的次数进行聚合,根据优先级逐个解决。另外,异常收集可配置预警规则。

屏幕快照 2020-06-22 下午3.20.39.png

引擎启动优化

问题:通过高可用监控发现页面打开的最大问题是耗时,根本原因是引擎初始化时间长。发现如下两类问题。

一,Flutter初始化时函数耗时长。例如iOS,在主线程执行创建GL Context占用了30%的时间。在子线程创建RootIsolate占用40%时间。页面渲染之前的Font Init模块耗时也较长。测试不同机型耗时100ms~200ms。
二,Flutter的主线程等待子线程执行完毕后才释放,浪费CPU。

一般优化策略:一是裁剪,裁剪对引擎的侵入性较大。二是异步化,最大程度利用CPU。若异步化做得详细,入侵性也较大,因此最合理方案是针对一两个较为耗时的问题进行优化。三是将一些耗时流程延后或提前。例如在Flutter创建引擎之前进行预热。只要不是首屏就用到Flutter的场景,预热是有效的优化方式。

UC优化方案:一,在子线程预创建GL Context,引擎初始化时将复用GL Context。二,在子线程预热RootIsolate。预热之后为了不占用内存将其关闭。三,异步化。四,优化Font Init。Font Init耗时的核心原因是做了多次dlopen,可通过添加变量控制dlopen做一次即可,这个改动后续会进行更加优雅的调优,目标是回到社区。

屏幕快照 2020-06-22 下午3.21.13.png

效果:预热的内存占用仅1.4M,相比预热整个引擎需要16M有很大优势,适合混合式开发,例如UC和手淘。预热的耗时性能提升了62%,异步方案在部分机型上有约100ms的优化。Font Init优化后在安卓部分机型耗时优化50ms~90ms。

视频外接纹理

UC在视频、图片组件使用的是外接纹理方案。

外接纹理原理:通过三个步骤完成外接纹理流程。第一,Flutter通知Native获取Texture id。第二,Native同步创建并注册Texture组件给Flutter。第三, Flutter创建textureWidget通过Texture id找到Texture组件,向skia绘制。

目前iOS和安卓的外接纹理流程存在差异。安卓使用到Surface Texture,iOS使用到Flutter Texture,需要Native回写CVPixelBuffer,Flutter内部会将CVPixelBuffer绑定到Texture,当CVPixelBuffer数据发生变化,Texture会向skia进行绘制。

屏幕快照 2020-06-22 下午3.22.00.png

问题:大部分解码出的视频格式是YUV,但Flutter内部CVPixelBuffer需要BGRA格式,需进行格式转换。如何使视频格式转换不影响性能?

优化:优先考虑在iOS端不修改引擎,通过高速纹理在GPU上把YUV转换为BGRA格式。Flutter内部CVPixelBuffer绑定Texture时使用到Binding API,相反,通过Binding API也可以将Texture绑定到CVPixelBuffer上。那么向Texture绘制YUV数据时设置BGRA的转换,这样两个Texture就通过CVPixelBuffer实现共享。该格式转换不耗时,并且不会使视频出现卡顿等问题。
屏幕快照 2020-06-22 下午3.22.19.png

问题:Flutter在外接纹理时使用默认的NEAREST算法,会将纹理附近的几个颜色进行加权平均使用,导致弧形斜线等锯齿明显。

优化:已经给官方提PR:https://github.com/flutter/flutter/issues/53080

屏幕快照 2020-06-22 下午3.22.57.png

图片组件优化-外接纹理方案

问题:Flutter和Native内存无法共享。
原生方式多图滑块的场景内存回收不及时,低端机会崩溃。

侧面反映出Flutter目前图片场景做的并不够优秀。

收益:图片组件场景可以享受Native组件库成熟的优化手段,例如LRU回收,多级缓存,线程池等。以及更多的图片格式支持,如iOS的HECI格式。

效果:内存占用较Flutter原生实现减少30%左右。内存回收表现更加及时。

屏幕快照 2020-06-22 下午3.23.15.png

四、动态性探索

业务需要:UC等以feed流业务为主的,社区类的产品,产品框架比较固定,内容的动态性最为关键,即需要提供给用户好看、热点的内容。在端侧内容入口的展现形式要与内容相匹配,例如运营位置、卡片样式,这部分是有动态性诉求的。而内容打开后的动态性更希望以Web方式解决。

业务诉求:需要轻量级的动态卡片解决方案。
解决方案:Flutter box项目,UC希望技术方案更加面向Flutter社区,选取Dart作为DSL描述。Dart有三点优势。

第一,Dart对UI的描述是结构化的。例如下方左侧代码,是Dart写法,通过组装式API编写对UI的描述。该模式的好处一方面是在AST转化为需要的协议时非常贴近、自然,令一方面对于模板开发者而言是自然的写法,无需做太多约束。
第二,Dart可一体式开发,从模板编写、预览到解析执行。
第三,支持Dart语法的表达式。例如下图右侧表达式,定义了一个create函数,可在build时调用。create函数声明List的对象,通过一次for循环创建Widget将其返回给build的container。实现了动态创建Widget树的方案。

屏幕快照 2020-06-22 下午3.25.00.png

效果:将Flutter box方案落地到夸克书城,一方面提升了运营能力,一方面提升了页面加载、滑动速度,给业务带来的正向反馈。

根据测试所得性能数据,转换耗时100ms,滑动帧率50fps。转换过程指文件首先在端侧解析为中间树,为其绑定数据,再将中间树转换为Dart需要的Widget树。业务数据表现为书城点击率提升2%。

屏幕快照 2020-06-22 下午3.25.16.png

五、总结

发展阶段

现阶段UC Flutter处于规模化落地阶段。

工程构建体系

搭建了标准的工程架构。为创新业务提供了可复用的运行时容器。抽象业务核心模块,使研发具备一致认知。

性能优化

构建了性能监控体系,针对核心场景的视频、图片性能和体感进行了优化。并且性能优化方案对Flutter原生引擎修改尽可能少。

动态性探索

从业务需要出发,落地了轻量级动态卡片,满足了运营能力。

未来

UC将更加深入地挖掘Flutter,包括对引擎的优化,充分体现出Flutter在效率、性能方面的优势,为业务赋能。

屏幕快照 2020-06-22 下午3.26.13.png
关注「淘系技术」微信公众号,一个有温度有内容的技术社区~
image.png

相关文章
|
12天前
|
缓存 监控 前端开发
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
【4月更文挑战第30天】本文探讨了Flutter应用启动优化策略,包括理解启动过程、资源加载优化、减少初始化工作、界面布局简化、异步初始化、预加载关键数据、性能监控分析以及案例和未来优化方向。通过这些方法,可以缩短启动时间,提升用户体验。使用Flutter DevTools等工具可助于识别和解决性能瓶颈,实现持续优化。
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
|
12天前
|
Dart 前端开发 测试技术
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践
【4月更文挑战第30天】随着Flutter在跨平台开发的普及,保证代码质量成为开发者关注的重点。优质代码能确保应用性能与稳定性,提高开发效率。关键策略包括遵循最佳实践,编写可读性强的代码,实施代码审查和自动化测试。重构实践在项目扩展时尤为重要,适时重构能优化结构,降低维护成本。开发者应重视代码质量和重构,以促进项目成功。
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践
|
12天前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
12天前
|
Dart 前端开发 安全
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
【4月更文挑战第30天】本文探讨了Flutter中线程管理和并发编程的关键性,强调其对应用性能和用户体验的影响。Dart语言提供了`async`、`await`、`Stream`和`Future`等原生异步支持。Flutter采用事件驱动的单线程模型,通过`Isolate`实现线程隔离。实践中,可利用`async/await`、`StreamBuilder`和`Isolate`处理异步任务,同时注意线程安全和性能调优。参考文献包括Dart异步编程、Flutter线程模型和DevTools文档。
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
|
12天前
|
Dart 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的性能分析工具Profiler
【4月更文挑战第30天】Flutter Profiler是用于性能优化的关键工具,提供CPU、GPU、内存和网络分析。它帮助开发者识别性能瓶颈,如CPU过度使用、渲染延迟、内存泄漏和网络效率低。通过实时监控和分析,开发者能优化代码、减少内存占用、改善渲染速度和网络请求,从而提升应用性能和用户体验。定期使用并结合实际场景与其它工具进行综合分析,是实现最佳实践的关键。
【Flutter前端技术开发专栏】Flutter中的性能分析工具Profiler
|
12天前
|
前端开发 数据处理 Android开发
【Flutter 前端技术开发专栏】Flutter 中的调试技巧与工具使用
【4月更文挑战第30天】本文探讨了Flutter开发中的调试技巧和工具,强调其在及时发现问题和提高效率上的重要性。介绍了基本的调试方法如打印日志和断点调试,以及Android Studio/VS Code的调试器和Flutter Inspector的使用。文章还涉及调试常见问题的解决、性能和内存分析等高级技巧,并通过实际案例演示调试过程。在团队协作中,有效调试能提升整体开发效率,而随着技术发展,调试工具也将持续进化。
【Flutter 前端技术开发专栏】Flutter 中的调试技巧与工具使用
|
12天前
|
Dart 前端开发 Java
【Flutter前端技术开发专栏】Flutter中的内存泄漏检测与解决
【4月更文挑战第30天】本文探讨了Flutter应用中的内存泄漏检测与解决方法。内存泄漏影响性能和用户体验,常见原因包括全局变量、不恰当的闭包使用等。开发者可借助`observatory`工具或`dart_inspector`插件监测内存使用。解决内存泄漏的策略包括避免长期持有的全局变量、正确管理闭包、及时清理资源、妥善处理Stream和RxDart订阅、正确 disposal 动画和控制器,以及管理原生插件资源。通过这些方法,开发者能有效防止内存泄漏,优化应用性能。
【Flutter前端技术开发专栏】Flutter中的内存泄漏检测与解决
|
12天前
|
缓存 监控 前端开发
【Flutter前端技术开发专栏】Flutter应用的性能调优与测试
【4月更文挑战第30天】本文探讨了Flutter应用的性能调优策略和测试方法。性能调优对提升用户体验、降低能耗和增强稳定性至关重要。优化布局(避免复杂嵌套,使用`const`构造函数)、管理内存、优化动画、实现懒加载和按需加载,以及利用Flutter的性能工具(如DevTools)都是有效的调优手段。性能测试包括基准测试、性能分析、压力测试和电池效率测试。文中还以ListView为例,展示了如何实践这些优化技巧。持续的性能调优是提升Flutter应用质量的关键。
【Flutter前端技术开发专栏】Flutter应用的性能调优与测试
|
12天前
|
前端开发 定位技术 API
【Flutter前端技术开发专栏】Flutter中的第三方服务集成(如支付、地图等)
【4月更文挑战第30天】本文介绍了在Flutter中集成第三方服务,如支付和地图,以增强应用功能和用户体验。开发者可通过官方或社区插件集成服务,关注服务选择、API调用、错误处理和用户体验。支付集成涉及选择服务、获取API密钥、引入插件、调用API及处理结果。地图集成则需选择地图服务、获取API密钥、初始化地图并添加交互功能。集成时注意选择稳定插件、阅读文档、处理异常、优化性能和遵循安全规范。随着Flutter生态发展,更多第三方服务将可供选择。
【Flutter前端技术开发专栏】Flutter中的第三方服务集成(如支付、地图等)
|
Dart JavaScript API
Flutter技术解析与实战——闲鱼技术演进与创新-第1章(10)
本书将详细讲解闲鱼Flutter&FaaS云端一体化架构,以及闲鱼基于Flutter的架构演进与创新,学习一套全面的Flutter架构应用方案。本书介绍闲鱼技术团队利用Flutter技术改造和上线复杂业务的混合工程改造实践,抽取Flutter依赖到远程的实现细节,以及使用Plugin桥接获取设备信息、使用基础网络库等混合开发实践指南。这些实践遍布闲鱼各大业务线和应用场景,为读者使用Flutter打造自己的研发体系探索一条实践之路。除了介绍闲鱼Flutter应用框架Fish Redux、开发利器AspectD、FlutterBoost等一众开源工具与开发实践指南,你还将在......
Flutter技术解析与实战——闲鱼技术演进与创新-第1章(10)