UC Flutter技术实践分享-阿里云开发者社区

开发者社区> 新零售淘系技术> 正文

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

淘系技术部隶旗下包含淘宝技术、天猫技术、农村淘宝技术、闲鱼、iHome等团队和业务,是一支是具有商业和技术双重基因的螺旋体。 我们致力于成为全球最懂商业的技术创新团队,打造消费者和商家一体化的新零售智能商业平台,创新商业赛道。随着新零售业务的持续探索与快速发展,我们不断吸引用户增长、机器学习、视觉算法、音视频通信、数字媒体、端侧智能等领域全球顶尖专业人才加入,让科技引领面向未来的商业创新和进步。欢迎投递简历至ruoqi.zlj@taobao.com

官方博客
淘系开源,欢迎star哟