闲鱼基于 Flutter 的架构演进与创新

标签: dev | 发表时间:2019-06-26 00:00 | 作者:
出处:http://itindex.net/relian

讲师介绍

2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地。未来将持续关注终端技术的演变及趋势。

Flutter的优势与挑战

Flutter是Google开源的跨端便携UI工具包,除了具有非常优秀的跨端渲染一致性,还具备非常高效的研发体验,丰富的开箱即用的UI组件,以及跟Native媲美的性能体验。由于它的众多优势,也使得Flutter成为了近些年来热门的新技术。

通过以上的特点可以看出,Flutter可以极大的加速客户端的研发效率,与此同时得到优秀的性能体验,基于我的思考,Flutter会为以下团队带来较大的收益:

  • 中小型的客户端团队非常适合Flutter开发,不仅一端编写双端产出,还有效的解决了小团队需要双端人员(iOS:Android)占比接近1:1的限制,在项目快速推进过程中,能让整个团队的产能最大化。

  • App在Android市场占比远高于iOS的团队,比如出海东南亚的一些App,Android市场整体占比在90%以上,通过Flutter可以将更多的人力Focus在Android市场上,同时通过在iOS端较小的投入,在结果上达到买一送一的效果。

  • 以量产App为主要策略的团队,不论是量产ToB的企业App,还是有针对性的产出不同领域的ToC的App的公司,都可以通过一端开发多端产出的Flutter得到巨大的产能提升。

闲鱼在以上的场景中属于第一种场景,服务3亿用户的闲鱼App的背后,开发资源投入并不多,与竞对相比,我们是一只再小不过的团队,在这种场景下,Flutter为闲鱼业务的稳定发展以及提供更多的创新产品给予了很大的帮助。

但与此同时,Flutter在设计上带来的优势同时又会带来新的问题。所有的新技术都是脱胎于老技术的,Flutter也不例外,其身上带有很多Chrome的影子。我们再做一层简化,如果我们认为Flutter是一个使用Dart语言的浏览器容器,请大家思考一下两个问题如何解决。

  • 如果在一个已经存在的App中加入Flutter,如何让Native与Flutter进行无缝的衔接,同时保证相互开发之间的隔离性

  • 如果在Flutter的容器中,使用已有的Native UI组件,在Flutter与Native渲染机制不同的情况下,怎么保证两者的无缝衔接以及高性能。

闲鱼的架构演进与创新

带着上面两个问题,我们来到闲鱼场景下的具体Case以及解决方案的演进过程。

已有App+Flutter容器

在这种情况下,闲鱼需要考虑的是首先要考虑引入Flutter容器后的内存压力,保证不要产生更多的内存溢出。与此同时我们希望能让Flutter和Native之间的页面切换是顺畅的,对不同技术栈之间的同学透明。因此我们有针对性的进行了多次迭代。

在没有任何改造的情况下以iOS为例,你可以通过创建新的FlutterViewController来创建一个新的Flutter容器,这个方案下,当创建多个FlutterViewController时会同时在内存中创建多个Flutter Engine的Runtime(虽然底层Dart VM依然只有一个),这对内存消耗是相当大的,同时多个Flutter Engine的Runtime会造成每个Runtime内的数据无法直接共享,造成数据同步困难。

这种情况下,闲鱼选择了全局共享同一个FlutterViewController的方式保证了内存占用的最小化,同时通过基础框架Flutter Boost提供了Native栈与Flutter栈的通信与管理,保证了当Native打开或关闭一个新的Flutter页面时,Dart侧的Navigator也做到自动的打开或关闭一个新的Widget。目前Google官方的提供的方案上就是参考闲鱼早先的这个版本进行的实现的。

然而在这种情况下,如果出现如闲鱼图中所示多个Tab的场景下,整个堆栈逻辑就会产生混乱,因此闲鱼在这个基础上对Flutter Boost的方案进行了升级并开源,通过在Dart侧提供一个BoostContainerManager的方式,提供了对多个Navigator的管理能力,如果打比方来看这件事,就相当于,针对Flutter的容器提供了一个类似WebView的OpenWindow的能力,每做一次OpenWindow的调用,就会产生一个新的Navigator,这样开发者就可以自由的选择是在Navigator里进行Push和Pop,还是直接通过Flutter Boost新开一个Navigator进行独立管理。

Flutter Boost目前已在github开源,由于闲鱼目前线上版本只支持Flutter 1.2的版本,因此需要支持1.5的同学等稍等,我们会在近期更新支持1.5的Flutter Boost版本。

Flutter页面+Native UI

由于闲鱼是一个闲置交易社区,因此图片和视频相对较多,对图片视频的线上性能以及内存占用有较严格的要求。目前Flutter已提供的几种方案中(Platform View以及Flutter Plugin),不论是对内存的占用还是整个的线上流畅度上还存在一定的问题,这就造成了当大部分同学跟闲鱼一样实现一个复杂的图文Feed推荐场景的时候,非常容易产生内存溢出。而实际上,闲鱼在以上的场景下有针对性的做出了较大的优化。

在整个的Native UI到Flutter渲染引擎桥接的过程中,我们选用了Flutter Plugin中提供的FlutterTextureRegistry的能力,在去年上半年我们优先针对视频的场景进行了优化,优化的思路主要是针对Flutter Engine底层的外接纹理接口进行修改,将原有接口中必须传入一个PixelBuffer的内存对象这一限制做了扩展,增加一个新的接口保证其可以传入一个GPU对象的TextureID.

如图中所示,优化后的整个链路Flutter Engine可以直接通过Native端已经生成好的TextureID进行Flutter侧的渲染,这样就将链路从Native侧生成的TextureID->copy的内存对象PixelBuffer->生成新的TextureID->渲染,转变为Native侧生成的TextureID->渲染。整个链路极大的缩短,保证了整个的渲染效率以及更小的内存消耗。闲鱼在将这套方案上线后,又尝试将该方案应用于图片渲染的场景下,使得图片的缓存,CDN优化,图片裁切等方案与Native归一,在享受已有集团中间件的性能优化的同时,也得到了更小的内存消耗,方案落地后,内存溢出大幅减少。

目前该方案由于需要配合Flutter Engine的修改,因此暂时无法提供完整的方案至开源社区,我们正在跟google积极沟通整个修改方案,相信在这一两个月内会将试验性的Engine Patch开源至社区,供有兴趣的同学参考。

复杂业务场景的架构创新实践

将以上两个问题解决以后,闲鱼开始了Flutter在业务侧的全面落地,然而很快又遇到新的问题,在多人协作过程中:

  • 如何提供一些标准供大家进行参考保证代码的一致性

  • 如何将复杂业务进行有效的拆解变成子问题

  • 如何保证更多的同学可以快速上手并写出性能和稳定性都不错的代码

在方案的前期,我们使用了社区的Flutter Redux方案,由于最先落地的详情,发布等页面较为复杂,因此我们有针对性的对View进行了组件化的拆分,但由于业务的复杂性,很快这套方案就出现了问题,对于单个页面来说,State的属性以及Reducer的数量都非常多,当产生新需求堆叠的时候,修改困难,容易产生线上问题。

针对以上的情况,我们进行了整个方案的第二个迭代,在原有Page的基础上提供了Component的概念,使得每个Component具备完整的Redux元素,保证了UI,逻辑,数据的完整隔离,每个Component单元下代码相对较少,易于维护和开发,但随之而来的问题是,当页面需要产生数据同步时,整个的复杂性飙升,在Page的维度上失去了统一状态管理的优势。

在这种情况下闲鱼换个角度看端侧的架构设计,我们参考React Redux框架中的Connect的思想,移除掉在Component的Store,随之而来的是新的Connector作为Page和Component的数据联通的桥梁,我们基于此实现了Page State到Component State的转换,以及Component State变化后对Page State的自动同步,从而保证了将复杂业务有效的拆解成子问题,同时享受到统一状态管理的优势。与此同时基于新的框架,在统一了大家的开发标准的情况下,新框架也在底层有针对性的提供了对长列表,多列表拼接等case下的一些性能优化,保证了每一位同学在按照标准开发后,可以得到相对目前市面上其他的Flutter业务框架相比更好的性能。

目前这套方案Fish Redux已经在github开源,目前支持1.5版本,感兴趣的同学可以去github进行了解。

研发智能化在闲鱼的应用

闲鱼在去年经历了业务的快速成长,在这个阶段上,我们同时进行了大量的Flutter的技术改造和升级,在尝试新技术的同时,如何能保证线上的稳定,线下的有更多的时间进行新技术的尝试和落地,我们需要一些新的思路和工作方式上的改变。

以我们日常工作为例,Flutter的研发同学,在每次开发完成后,需要在本地进行Flutter产物的编译并上传到远端Repo,以便对Native同学透明,保证日常的研发不受Flutter改造的干扰。在这个过程中,Flutter侧的业务开发同学面临着很多打包上传更新同步等繁琐的工作,一不小心就会出错,后续的排查等让Flutter前期的开发变成了开发5分钟,打包测试2小时。同时Flutter到底有没有解决研发效率快的问题,以及同学们在落地过程中有没有Follow业务架构的标准,这一切都是未知的。

在痛定思痛以后,我们认为数据化+自动化是解决这些问题的一个较好的思路。因此我们首先从源头对代码进行管控,通过commit,将代码与后台的需求以及bug一一关联,对于不符合要求的commit信息,不允许进行代码合并,从而保证了后续数据报表分析的数据源头是健康的。

在完成代码和任务关联后,通过webhook就可以比较轻松的完成后续的工作,将每次的commit有效的关联到我们的持续集成平台的任务上来,通过闲鱼CI工作平台将日常打包自动化测试等流程变为自动化的行为,从而极大的减少了日常的工作。粗略统计下来,在去年自动化体系落地的过程中单就自动打Flutter包上传以及触发最终的App打包这一流程就让每位同学每天节省一个小时以上的工作量,效果非常明显。另外,基于代码关联需求的这套体系,可以相对容易的构建后续的数据报表对整个过程和结果进行细化的分析,用数据驱动过程改进,保证新技术的落地过程的收益有理有据。

总结与展望

回顾一下上下文,

  • Flutter的特性非常适合中小型客户端团队/Android市场占比较高的团队/量产App的团队。同时由于Flutter的特性导致其在混合开发的场景下面存在一定劣势。

  • 闲鱼团队针对混合开发上的几个典型问题提供了对应的解决方案,使整个方案达到上线要求,该修改会在后续开放给google及社区。

  • 为全面推动Flutter在业务场景下的落地,闲鱼团队通过多次迭代演进出Fish Redux框架,保证了每位同学可以快速写出相对优秀的Flutter代码。

  • 新技术的落地过程中,在过程中通过数据化和自动化的方案极大的提升了过程中的效率,为Flutter在闲鱼的落地打下了坚实的基础。

除了本文提及的各种方案外,闲鱼目前还在多个方向上发力,并对针对Flutter生态的未来进行持续的关注,分享几个现在在做的事情:

  • Flutter整个上层基础设施的标准化演进,混合工程体系是否可以在上层完成类似Spring-boot的完整体系构架,帮助更多的Flutter团队解决上手难,无行业标准的问题。

  • 动态性能力的扩展,在符合各应用商店标准的情况下,助力业务链路的运营效率提升,保证业务效果。目前闲鱼已有的动态化方案会后续作为Fish-Redux的扩展能力提供动态化组件能力+工具链体系。

  • Fish-Redux + UI2Code,打通代码生成链路和业务框架,保证在团队标准统一的情况下,将UI工作交由机器生成。

  • Flutter + FaaS,让客户端同学可以成为全栈工程师,通过前后端一体的架构设计,极大的减少协同,提升效率。

让工程师去从事更多创造性的工作,是我们一直努力的目标。闲鱼团队也会在新的一年更多的完善Flutter体系的建设,将更多已有的沉淀回馈给社区,帮助Flutter社区一起健康成长。


相关推荐

已开源|2亿用户背后的Flutter应用框架Fish Redux


重磅系列文章|“UI2Code”智能生成Flutter代码


老代码多=过度耦合=if else?阿里工程师这么捋直老代码



更多系列文章、开源项目、关键洞察、深度解读

请持续关注 闲鱼技术

相关 [flutter 架构 创新] 推荐:

闲鱼基于 Flutter 的架构演进与创新

- - IT瘾-dev
2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地. 未来将持续关注终端技术的演变及趋势. Flutter是Google开源的跨端便携UI工具包,除了具有非常优秀的跨端渲染一致性,还具备非常高效的研发体验,丰富的开箱即用的UI组件,以及跟Native媲美的性能体验.

闲聊 Flutter

- - bang’s blog
移动端开发从08年开始就有个大家前赴后继不断追求的目标:跨平台,15年时 nwind 有篇 雄文,详细调研了跨平台各流派,其中最后的 Dart 栏可以看到现在 Flutter 的雏形. 可以看出来,Flutter 是从精简浏览器的思路演化过来的,实际上 web 与 Flutter 从底层看是一致的,web 是提供了一层平台无关的独立引擎,可以看成平台只提供了画布,所有的UI组件、框架、事件处理都是 web 引擎封装处理.

Flutter Weekly Issue 51

- - IT瘾-dev
一个易用的 Flutter 应用页面事件埋点插件. 它不仅支持在普通导航事件中监听页面曝光和离开,也支持弹窗的曝光和离开. flutter滑动曝光埋点框架,支持SliverList、SliverGrid. Inner Drawer is an easy way to create an internal side section (left/right) where you can insert a list-menu or other..

Flutter原理与实践

- - 美团点评技术团队
Flutter是Google开发的一套全新的跨平台、开源UI框架,支持iOS、Android系统开发,并且是未来新操作系统Fuchsia的默认开发套件. 自从2017年5月发布 第一个版本以来,目前Flutter已经发布了近60个版本,并且在2018年5月发布了第一个 “Ready for Production Apps”的Beta 3版本,6月20日发布了第一个 “Release Preview”版本.

一个 Demo 入门 Flutter

- - limboy's HQ
Flutter 是 Google 研发的一套移动端开发框架,也是 Google 正在研发的下一代操作系统 Fuchsia 的 App 开发框架(Web 和 Desktop 也都在进行积极的尝试),前几天刚发布了 1.0 正式版. 关于 Flutter 的原理和介绍可以参考美团的 这篇文章. 本文希望通过一个 Demo 来更深入地了解 Flutter 的布局、状态管理等细节.

Flutter Go:Flutter 开发者帮助 App

- - IT瘾-dev
帮助开发者快速上手 Flutter 内部测试中,1.0 正式版将于 2月 20日 发布. Release安装包下载地址. iphone下载地址: 暂无. Flutter 是什么?. 2018年6月21日Google发布Flutter首个release预览版,作为Google 大力推出的一种全新的响应式,跨平台,高性能的移动开发框架.

Flutter 2019 产品路线图正式公布

- - SegmentFault 最新的文章
Flutter 1.0 的发布对我们来说是一个很重要的起点,长路漫漫,我们仍有很多工作要做. 这里我们向大家公开我们的产品路线图(Roadmap)规划,一方面是保持开源项目的透明度,另一方面,开发者们也可以根据我们的工作优先级来制定更适合的工程方案. 以下几点我们今年会着重关注:. 我们的计划会根据大家的反馈以及新的市场变化来做调整,这份路线图里的内容不尽然是我们一定会完成的工作.

移动跨平台框架Flutter介绍和学习线路

- - SegmentFault 最新的文章
Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序. Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序. 我们兼容滚动行为、排版、图标等方面的差异. 在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的.

让前端开发者失业的技术,Flutter Web初体验

- - SegmentFault 最新的文章
Flutter是一种新型的“客户端”技术. 它的最终目标是替代包含几乎所有平台的开发:iOS,Android,Web,桌面;做到了一次编写,多处运行. 掌握Flutter web可能是Web前端开发者翻盘的唯一机会. 在前些日子举办的Google IO 2019 年度开发者大会上,Flutter web作为一个很亮眼的技术受到了开发者的追捧.

从Flutter聊聊跨平台移动研发方案

- - 掘金 架构
Flutter 是一款由 Google 开发的开源、跨平台移动端开发框架. Flutter 使用 Dart 作为开发语言,这是一门简洁、强类型的编程语言. 它允许使用同一个代码库构建高性能、漂亮的 iOS 和 Android 应用,Flutter还提供了两套视觉库,可以针对不同的平台有不同的展示效果.