作者:闲鱼技术-凯航
Flutter是一个使用Dart语言开发的跨平台移动UI框架,通过自建绘制引擎,能高性能、高保真地进行Android和IOS开发。在业界还未出现过Base Flutter的大型商业应用实战验证的情况下,闲鱼技术团队在最复杂且重要的商品详情页作了相关的技术实践并取得良好的结果。现尝试通过本文向有兴趣进行类似实践的开发者或团队分享过程中的思考/实践过程。
Flutter特色
面对一系列移动开发技术:IOS、Android、Weex,RN, Kotlin,H5... Flutter究竟特色何在?

开发语言选择
了解过Flutter的都知道,它采用Dart语言进行开发,而并非Java,Javascript这类热门语言,这是Flutter团队对当前热门的10多种语言慎重评估后的选择。因为Dart囊括了多数编程语言的优点,它更符合Flutter构建界面的方式。

Flutter vs ReactNative框架对比
ReactNative | Flutter |
---|---|
![]() |
![]() |
ReactNative
- 采用Javascript开发,需学React,成本高
- 需要JavaScript桥接器,实现JS到Native转化,性能耗损
- 访问原生UI,频繁操作易出性能问题
- 支持线上动态性,可有效避免频繁更新版本
Flutter
- 采用Dart开发,可直接编译成Native代码(易学)
- 自带UI组件和渲染器,仅依赖系统提供的Canvas(无桥接耗损)
- 暂不支持线上动态性
Flutter更多特色可以链接为什么说Flutter是革命性的?
每个框架都是为解决特定问题而产生的,不存在最好的框架,只有最适合你团队的框架。闲鱼是个业务快速发展的App,为更多业务尝试和探索,它采用现有流行的框架,能支持线上动态化需求。但出于个性化交互以及流畅性体验(首页、商品详情、发布闲置等),主链路依旧只采用原生开发。为兼顾跨端开发及高性能需求,闲鱼经过充分调用,最终选择了Flutter。为验证Flutter的性能,闲鱼挑选重要且复杂的主链路业务(商品详情)作为首个Flutter页面实践点,以这种方式来快速暴露并解决Flutter相关问题。
闲鱼Flutter突破点
Flutter与Native混合编程方案
随着Flutter版本的不断迭代,稳定性和质量逐渐完善,市场上纯Flutter开发的App也不断涌现。闲鱼对Flutter采取“由点到面,逐一替换” 的策略,先将商品详情迁移到Flutter页面,后续逐步扩展到其他功能模块,但这样就不可避免涉及到Flutter与Native页面混合调用的场景(如下图):

Flutter | Native(Android) |
---|---|
![]() |
![]() |
因此要混合调用就会涉及两个问题:
- 混合栈管理
- 组件间调用
混合栈管理
Flutter出现的目的旨在统一Android/IOS两端编程,因此完全基于Flutter开发的App,只需提供一个包含FlutterView的页面,后续页面增加/删除/跳转均在FlutterView的Navigator中进行管理。但现在闲鱼只是将部分模块修改成Flutter开发,我们不可能为统一页面栈管理而将其他所有页面用Flutter重做一次,权衡成本与风险,亟需统一管理Native页面和Flutter页面跳转交互的混合栈。为此,闲鱼提出了4种解决方案(如下图):

- 每启动一个Activity就启动一个新的FlutterView(方案4);
- 抽取单一FlutterView或FlutterNativeView,后续每启动一个Activity都对FlutterView或FlutterNativeView进行复用(方案2或方案3);
考虑到每启动一个页面都新创建一套新的Flutter渲染机制,开销过重,目前闲鱼Flutter实践采用方案2,相比而言,该方案性能相对稳定且易操作,下面就是否复用FlutterView进行对比,主要观测Java内存和Native内存增加情况:

组件间调用

解决了Flutter与Native混合编程所面临的问题后,接下来要处理的就是混编工程问题,出现该问题的原因还是我们的项目不是完全的Flutter工程(即:android /ios + Flutter)所致。混合工程项目结构以及Flutter产物如下图:
项目结构

Flutter产物

其实对一般Flutter工程而言,采用AndroidStudio编译Flutter与编译Native工程方式一样,当将其部署到server端采用mtl编译时,server缺少Flutter编译环境,因而导致Flutter工程无法编译。解决此问题可以采取两种方式:
- 在每个server端部署Flutter编译环境
- Native工程远程依赖Flutter编译产物
对1,对各server端都去部署Flutter环境有点不切实际(若server就那么几台也可以);对2,闲鱼的做法是将Flutter工程编译出的中间产物以AAR形式导出并上传至maven库,最后Native工程以依赖包形式将AAR打入最终apk中,这样处理后解耦了Native团队对Flutter团队的依赖。当然,具体实践过程中肯定没有这么简单,我们在编译过程中对Pod/Gradle编译脚本、engine以及flutter_tools等均有所优化,对后续集团推广Flutter奠定了基础。
阿里Flutter生态适配
将Flutter应用于闲鱼,不可避免需要使用集团提供的基础组件库,但这些组件库都是Native,考虑到为后续Flutter在集团推广,打造阿里Flutter生态圈,闲鱼团队对集团内部基础组件库做了适配支撑,后续可建立私有仓库,直接Git引用。
生态适配原理及性能

多媒体解决方案
在以内容为王的时代,多媒体技术备受关注,性能的好坏直接影响用户体验,但Flutter多媒体默认功能存在以下缺陷:
- 功能单一,如:播放器缺少滤镜,与Native淘宝播放器存在一定差距
- 兼容性欠佳
为改善体验,优化性能,闲鱼对Flutter播放器以及图片性能作出如下改进:
Texture对接自定义视频播放器

具体方案:

图片性能优化
有过移动开发经验的都知道,图片展示是OOM出现的高频场景,而Flutter默认采用基于LRU算法的图片缓存策略,且图片缓存MaxSize=1000,占用内存较高,为此闲鱼采用以下两种策略对图片性能进行优化

Flutter 上线效果 & 性能对比 & 成熟度
解决了Flutter存在的问题,要的就是产品能够以一种性能稳定、交互流畅、界面美观的姿态呈现在用户面前,下面就以闲鱼宝贝详情线上Flutter版本为引,对Flutter应用页面展示、性能以及成熟度进行阐述。
闲鱼宝贝详情Flutter应用线上效果
Native性能对比
测试环境
- 测试机型:iphone6
- IOS版本:11.3
- 闲鱼版本: 6.1.3
- 测试方法: 在Flutter版本和Native版本各自宝贝详情页面执行相同操作:即从我发布的页面进行10个不同详情页面
注: 下图仅对Flutter和Native性能进行了粗略对比

Flutter成熟度

延展讨论
目前Flutter尚处于Preview阶段,没有经过大规模实践验证,框架成熟度及稳定性仍有待完善。上文仅仅是将闲鱼团队在实践Flutter开发时碰到部分问题及解决方案进行了简略阐述,一个产品从开发到上线所面临的问题,肯定远不及这些。随着Flutter覆盖场景的增加,难题也会不断涌现,健全有效的性能及稳定性监控体系不可或缺。为建设基于Flutter全新的一体化研发体系,提高开发效率,对动态化需求、规范Dart编码、统一中间件桥接机制、快速发版能力及完备的自动化测试建设等一系列问题亟需解决,倘若您对此感兴趣,欢迎一起交流学习~
简历投递:guicai.gyx@alibaba-inc.com