Flutter在京东7FRESH的业务实践

GodwinMorton 发布于5月前
0 条问题

2018年12月Flutter 1.0正式版本发布,与此同时,7FRESH也选择在活动页、7Club、接龙及返佣等垂直业务中使用Flutter开发并灰度上线。具体页面如下:

Flutter在京东7FRESH的业务实践

 

 

 

如上所示,上边是使用Flutter开发的活动页,下边是使用H5开发的活动页,可以很直观地感受到用Flutter开发的页面,在打开页面时白屏时间更短,体验更好,这也是我们选择Flutter的原因。

基本架构

在实际开发的过程中,并形成了适合我们的基本架构,如下图所示:

Flutter在京东7FRESH的业务实践

分别为 业务层和通用组件层; 通用组件层包含了业务组件、UI组件、基础组件;

  • 业务层 就是基于通用组件层开发的具体业务,比如接龙、活动页、返佣、晒单等具体业务;

  • 业务组件 中包括了分享、统计埋点、通用商品组等通用的组件,可以为各个业务模块,提供快速复用的能力;

  • UI组件 中主要是包括通用的Widget,如Button、CoutDown、Swiper等;

  • 基础组件 为上层提供统一的基础能力,如混合页面栈管理、路由管理、图片缓存、热更新等。

我们遇到的问题

7FRESH App 也是基于原有的基础库和业务组件这样的前提下,去做Flutter实践;在这个过程中也踩过很多坑;比如:状态管理怎么做?怎样混合开发及工程管理?页面栈管理?图片缓存问题?Native通信及如何复用已有功能?性能分析?

状态管理方案

我们先比较一下状态管理的方案:

Flutter在京东7FRESH的业务实践

综合原因,我们目前采用Provider作为状态管理的方案,一方面Provider解决了刷新范围问题,使用相对简单,提高了性能,职责相对清晰;另一方面也是Google推荐的状态管理方案;Provider使用如下:

1、首先在pubspec.yaml中增加provider依赖

Flutter在京东7FRESH的业务实践

2、定义Model,这里使用mixin,混入了ChangeNotifier,调用notifyListeners()通知刷新 

Flutter在京东7FRESH的业务实践

3、我们需要页面中build方法中注册共享的Model;由于多状态管理,所以使用到了MultiProvider和具备通知刷新功能的ChangeNotifierProvider

Flutter在京东7FRESH的业务实践

4、比如,购物车数量展示,这是一个局部刷新的需求,首先上图中我们已经注册CartNumModel,然后我们通过消费者Consumer获取新的状态,实现局部刷新。如下:

Flutter在京东7FRESH的业务实践

问题来了,Provider是如何实现刷新颗粒度的控制?如下:

1、Provider通过InheritedProvider(继承了InheritedWidget)实现了状态的共享,如下

Flutter在京东7FRESH的业务实践

2、然后,ChangeNotifierProvider继承的ListenalbeProvider,其实是一个StatefulWidget,具备了状态变化的能力;

3、Model继承的ChangeNotifier,而ChangeNotifier是一个发布者-订阅者模式,所以具备了通知刷新的能力;

4、ChangeNotifierProvider在初始化时,通过混入的代理对象_ListenableDelegateMixin<T extends Listenable> 把setState注册到Model,核心代码如下:

Flutter在京东7FRESH的业务实践

5、而Model在通过notifyListeners()通知刷新时,就是调用上图listener的Function,调用listener即调用setState,如下,从而达到局部刷新的过程.

Flutter在京东7FRESH的业务实践

混合开发及工程管理

对于代码管理,Android、iOS、Flutter对应三个git仓库,分别管理;

工程管理及工程模式上,通常有两种方式;

一种是源码依赖。优点就是集成便捷,方便调试,修改flutter代码,实时运行代码即可生效,便于调试;缺点就是团队其他开发人员必须都需要安装flutter编译环境。首先我们将flutter工程和Native工程放在同一目录下;

对于Android,在原生项目中做如下修改,首先在settings.gradle中增加配置:

Flutter在京东7FRESH的业务实践

然后在app的build.gradle中增加flutter依赖即可,如下:

Flutter在京东7FRESH的业务实践

对于iOS,也可参考官方步骤,为了方便开发,我们修改了点内容,官方脚本中在打包的时候是flutter.framework支持模拟器,所以在提交appstore的时候是提交不成功的,所以我们修改了一下脚本,在release模式下,从framework中移除了对模拟器的支持。如下,在Podfile中增加如下配置:

Flutter在京东7FRESH的业务实践

在"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"文件中修改以下配置,为了不影响sdk环境,可以复制此脚本作为副本,xcode的build phases菜单中单独引用.

Flutter在京东7FRESH的业务实践 Flutter在京东7FRESH的业务实践

另一种是构建产物依赖。优点就是不影响原生项目,其他开发人员不需要任何配置和安装环境,基本无感知的,缺点就是调试和定位问题比较麻烦。对于Android,Flutter构建生成aar,通过gradle依赖接入即可,对于iOS,Flutter端构建生成framework,通过以pod方式依赖接入即可;构建产物依赖也为后续通过maven管理及组件化创建了条件。

目前,我们在debug模式下使用的源码依赖,在release下使用了构建产物依赖,编译时通过是否debug进行区分,大概如下:

Flutter在京东7FRESH的业务实践

混合页面栈管理

我们采用了Flutter引擎共享的方式去解决内存问题,同时借鉴WebView管理页面栈的方式管理Flutter栈,采用全局路由协议进行页面间的通信和跳转.

全局路由管理

协议定义如图,每一个部分都是变量.

Flutter在京东7FRESH的业务实践

基于MethodChannel传递数据,通过路由协议实现跨技术栈访问Native\H5\Flutter\RN,不用关心此功能是用什么技术栈实现;同时,解耦模块间的跳转或功能的调用;也解决了Native功能复用的问题;

网络模块

目前是通过路由协议复用Native网络的能力:一方面Native侧对网络做了一系列优化,如HTTPDNS、HTTPS的验证等等;一方面基于资源的投入,短时间内很难做到Native的优化;Flutter本身的网络库,如dio也是不错的选择。埋点和分享目前也是通过路由协议复用Native端的能力;通过路由协议的好处是不用关心具体实现.

图片缓存方案

我们研究了fade_in_image、cache_network_image缓存库,fade_in_image仅支持内存缓存;cache_network_image文件缓存策略无法满足我们的要求,最终,我们选择了基于fade_in_image作为基础,进行了扩展,优化内存缓存、增加二级缓存,同时使用LRU作为缓存管理策略.

性能分析对比

对于Flutter和H5运行性能对比我们分别在debug和release模式上进行了性能测试,当然release模式的性能是要高于debug模式的,因此以下我们就debug模式的检测数据对Flutter与H5进行性能对比分析。这里我们用Android Profiler进行性能指标检测,下图分别是接龙列表Flutter与H5页面的性能检测数据:

Flutter在京东7FRESH的业务实践

Flutter在京东7FRESH的业务实践

首先,我们看 CPU,在启动的时候,Flutter对CPU的占用峰值在24.9%,然后页面加载完后降到了10%左右,之后也没有太大的波动,而H5对CPU的占用峰值达到了33%,之后也一直居高不下,偶尔有降低也很快回升,如图分析,H5相对于Flutter在绘制以及与Native交互通信方面对CPU的消耗高出很多。

内存上两者的峰值都超过了300M,但可以看出Flutter对内存的消耗是要稍高于H5的,页面数据加载完成之后趋于稳定,Flutter的稳定在302.3M,H5的稳定在257.2M。

最后再来看下帧率(FPS),这个是跟用户体验直接相关的,如果帧率过低导致丢帧页面卡顿的话,会直接影响App用户的留存率的,对于帧率,Flutter这边是用Flutter插件自带的Inspector工具来检测帧率变化的,H5则是打开了手机的GPU呈现模式分析,直接以条形图来展示帧率的变化。如下图:

Flutter在京东7FRESH的业务实践

从上图可以看出Flutter的渲染指数是很高的,它自带有渲染引擎,这使得Flutter页面渲染滑动时更平滑顺畅,交互更加友好。

通过以上分析我们可以得出结论,Flutter除了在内存消耗方面要稍高于H5外(项目中Flutter使用了引擎复用,所以在首次打开时内消耗较大,再次打开内存消耗小很多),在CPU资源占用、渲染方面性能都要高于H5.

关于人效

经过这段时间的实践经验,在开发人效方面,同一个需求,使用Native和Flutter开发大概可以得出下面的数据:

Flutter在京东7FRESH的业务实践

如图所示,目前Android和iOS两端,使用Native开发,原来需要6人天的需求,使用Flutter只需求4人天,至少为我们节省了30%的人力;而节省的人力可以投入到其它的需求研发.  

未来期望与规划

Flutter 1.9.1版本已于9月中旬的GDD大会发布,其中支持web平台的Flutter已经合到主干,意味着更好地支持三端又近了一步,我们也会持续关注;同时,7FRESH也会和京东中台ARES跨端团队保持紧密的联系,在组件化、动态更新、工具支持化等方面持续发力,一起为京东内部及行业内的Flutter生态做出一点贡献.

下图为我们的技术交流群二维码,欢迎各位技术爱好者加入交流.

Flutter在京东7FRESH的业务实践

查看原文: Flutter在京东7FRESH的业务实践

  • beautifulcat
  • heavylion
  • whitecat
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。