• 注册
  • 前端博客 前端博客 关注:2 内容:1196

    开源|Fair在安居拍房App中的实践 荐

  • 查看作者
  • 打赏作者
  • 当前位置: 职业司 > 前端开发 > 前端博客 > 正文
    • 前端博客
    • F

      Fair2.0专题系列

      NO.7 Fair在安居客拍房App中的实践

      项目名称:Fair 2.0

      Github地址: 链接

      项目简介:Fair是为Flutter设计的动态化框架,可以通过Fair Compiler工具对Dart源文件的转化,使项目获得动态更新Widget的能力。Fair 2.0是为了解决 Fair 1.0版本的“逻辑动态化”能力不足。

      Fair2.0连载公告

      关于Fair 2.0详细的设计和原理介绍,请关注后续文章,我们会以连载的方式,逐步公开架构设计原理。

      文章开放频率为每周2篇,分别在周二和周四,敬请关注!

      《开源公告|Fair2.0逻辑动态化开源了!》

      《Fair逻辑动态化架构设计与实现》

      《Fair 逻辑动态化通信实现》

      《Fair 逻辑语法糖设计与实现》

      《Fair 下发产物-布局DSL生成原理》

      《Fair 热更新设计与实现》

      《Fair 下发产物-逻辑JS生成原理》

      《Flutter 动态化项目评测》

      随着今年政府对互联网的监管,在不少时候一个紧急需求只给1~2天整改上线,而且整改过程中需求也不是很明确,相关部门也不会给一个详细的需求文档让我们去开发,大家都是“猜测”需求的内容。在这种场景下,如果App具备动态更新的能力,会给公司减少很大的成本。面对需求不确定和紧急修改页面部分元素的能力,给予了动态化最合适的使用场景,而不只是Fix几个BUG。

      Fair在58集团内的部分Flutter App中已经落地,终使集成Fair后的App获得了动态化的能力。以下文章内容主要以安居拍房App为例,介绍集成Fair的架构、业务场景所需的能力预埋,以及如何进行原生和动态化代码的维护,持续发挥Flutter的性能。

      本篇文章主要介绍Fair在项目中不同场景的使用。具体的技术原理介绍,请查阅前面发布的《Fair逻辑动态化架构设计与实现》《Fair 逻辑动态化通信实现》


      1

      现有架构

      居拍房App是采用三端分离的混合开发模式,Flutter产物会以AAR或者Framework的方式集成到Android和iOS原生项目中。

      安居拍摄App主要是记录房源信息、拍摄房源图片和VR的功能,如何把现有的Flutter能力,改造成动态代码可调用功能,就需要把网络、权限管理、图片选择、VR拍摄等能力提前预埋,定好通信协议,以便后续动态模块可以正常使用。扩展Fair能力前的架构,如下所示:

      开源|Fair在安居拍房App中的实践
                                                
                                                    荐


      2

      能力预埋

      如上一节所说,如何把一些平台能力提供给Fair动态调用,这部分工作需要提前规划和预埋。下面我们从完整界面路由预埋、动态和原始组合展示、已有组件和模版注册和第三方SDK能力扩展5个方面进行介绍。

      2.1 完整界面

      统一动态界面注册

      FairApp(      child: MaterialApp(        home: ***,        routes: {          ***          // Fair动态页面跳转          'fair_page': (context) => FairWidget(              name: _getParams(context, 'name'),              path: _getParams(context, 'path'),              data: {'fairProps': jsonEncode(_getData(context, _getParams(context, 'name')))}),        },      ),)

      如上所示,Fair的界面调用统一注册在routes里面的fair_page来跳转,根据传入的path和参数来完成对应的动态界面的展示。

      统一动态界面调用

      // 动态界面Navigator.pushNamed(context, 'fair_page', arguments: {                'name': '动态界面 **',                'path':                    'assets/bundle/lib_src_page_logic-page_sample_logic_page.fair.json',                'data': {"fairProps": {'pageName': '动态界面 **', '_count': 58}}              });

      如上所示,跳转到动态界面我们使用Navigator.pushNamed来完成。这里有同学可能会问,一个原生界面不是早把跳转的方式固定写好了吗?这里得益于安居拍房App的Api动态路由的设计,在一个原生界面中,点击跳转的路由都是后端下发的,App根据Api返回路径完成目标界面的跳转。看到这里大家就明白了,Api路由管理除了方便A/B Test,以至于原生与H5、RN、Flutter都可以实现灵活动态切换。如果项目允许,也可以推广这种方案。

      2.2 界面部分元素

      与整个界面的动态化相比,界面部分元素的动态化,在实际需求场景中遇到比较多。比如需要在原生列表中增加一种类型item,Fair提供了FairWidget,方便跟原生组合显示。下面我们以在列表中预埋一个动态Item为例:

      // 列表ListView.builder(                padding: EdgeInsets.only(left: 20, right: 20),                itemCount: _response.list.length,                itemBuilder: (BuildContext context, int position) {                  return getItem(_response.list[position]);                })));

      // item 构建Widget getItem(var item) {// 根据后端item类型,选择是动态item还是原生item if (item.type == 'fair') { // 动态内容 return Container( alignment: Alignment.centerLeft, color: Colors.white, constraints: BoxConstraints(minHeight: 80), child: FairWidget( name: item.id, path: 动态资源名, data: {**参数**});
      } else { return Column( // 原生内容 ); }}

      2.3 使用本地Widget组件

      Fair除了在Widget文件头部增加@FairPatch()来实现整个界面的动态化转化,还提供了@FairBinding()注解来实现本地Widget注册成动态可使用的组件。

      本地Widget转化

      // 一个本地Widget界面,提供给界面动态时使用@FairBinding()class CardWidget extends StatelessWidget {  String text;
      CardWidget({this.text});
      @override Widget build(BuildContext context) { return Text( text, style: TextStyle(color: Colors.red), ); }}

      编译&注册

      // flutter pub run build_runner build 后注册到FairApp中FairApp(child: MyApp(), generated: AppGeneratedModule());

      动态界面中使用

      @FairPatch()class CardWidgetState extends State<CardWidget> {  @override  Widget build(BuildContext context) {    return Container(      color: Colors.yellow,      child: Column(        children: [          Row(            children: [              CardWidget(text: 'card 1'),            ],          )        ],      ),    );  }}

      2.4 逻辑模版使用

      由于Fair对原生Flutter类型的支持有限,同时为了避免高频的Dart与JS的通信,我们一般会考虑把算法和交互流程一致的代码,做成固定模版,只把显示相关的部分做成动态的。安居拍房App首页的就是一个任务列表,而且考虑到后续列表的使用场景比较多,我们需要预埋一个逻辑模版,方便后续动态列表的生成。Fair提供了Delegate方便我们做模版扩展,例如下面的下拉刷新列表:

      生产模版

      class ListDelegate extends FairDelegate {
      // 注册列表的构建方法 @override Map<String, Function> bindFunction() { var functions = super.bindFunction(); functions.addAll({ '_itemBuilder': _itemBuilder, '_onRefresh': _onRefresh, }); return functions; } // 通知JS侧 访问新的数据 Future<void> _onRefresh() async { await runtime?.invokeMethod(pageName, '_onRefresh', null); } // 得益于Fair是提供的第一层Widget Tree的组合,FairWidget可以完成动态的Widget的生成 Widget _itemBuilder(context, index) { var result = runtime?.invokeMethodSync(pageName, '_onItemByIndex', [index]); return FairWidget( name: itemData, path: '***', data: {'**'})}, ); }}

      如上代码所示,像_onRefresh方法由DSL中注册到Flutter ListView,ListView构建回调会自动访问到此方法,于是我们可以使用这些回调方法做一层跟JS侧的通信,来完成界面的数据更新和Item内容的动态展示。

      注册模版

      FairApp(      delegate: {        'ListLoadMore': (ctx, _) => ListDelegate(),      },      child: MaterialApp(        home: ***      ),    )

      如上所示,我们只需要把开发好的模版,注册到delegate中即可在DSL构建ListView的时候注册给系统。

      2.5 常用第三方SDK

      关于第三方或者自定义插件的使用,在FlutterApp中非常常用。安居拍房App几乎每个界面都需要使用网络,而且由于App的使用场景,拍摄和权限功能,也是必须要提前预埋,方便后续动态化界面的使用。下面我们以权限插件为例,如何扩展提供给动态场景使用。

      /// Fair 定义了第三方插件扩展的标准接口,开发者只需实现接口就可以使用底层的JS标准通信,这对开发者来说是无感知的class WBPermission extends IFairPlugin {
      Future<dynamic> requestPermission(map) async { // 根据从JS侧获得的map参数做具体的内容桥接 // 源Permission的状态获取 isGranted = await Permission.photos.request().isGranted;
      return Future.value(); }
      @override Map<String, Function> getRegisterMethods() { // 注册JS可调用的方法 var functions = <String, Function>{}; functions.putIfAbsent('requestPermission', () => requestPermission); return functions; }}

      3

      集成Fair后的架构

      集成Fair动态化SDK后,重点需要考虑对未来能力的思考,把一些平台能力扩展能动态可使用的组件。这里主要包括插件、现有Widget(添加Annotation)和一些模版等能力预埋。扩展Fair能力后的架构,如下所示:

      开源|Fair在安居拍房App中的实践
                                                
                                                    荐


      4

      部分效果展示

      4.1 界面

      开源|Fair在安居拍房App中的实践
                                                
                                                    荐

      如上图所示,得益于预先扩展了网络动态化支持和动态界面跳转,通过下发的Router协议可以很方便的构建一个完整的订单反馈界面。

      4.2 首页列表动态Item

      开源|Fair在安居拍房App中的实践
                                                
                                                    荐

      如上图所示,安居拍房App已经通过Flutter原生开发了一个首页列表,Fair除了支持把整个列表重新动态化,还支持一个更灵活的Item动态化。通过动态化的Item和点击后的动态界面Router跳转,很方便实现动态Item和进入的动态详情界面的功能。


      5

      版本管理

      Fair是通过Fair Compiler工具对源Dart文件进行转化,生产动态产物的。不像MXFlutter、Kraken基于JS技术栈来实现动态化。项目一旦通过JS去实现,性能的损失是不可逆的,但是Fair就是基于Dart开发,可以在处理紧急需求时,通过动态转化,在正常发版时使用源代码即可。整个版本管理流程如下:

      开源|Fair在安居拍房App中的实践
                                                
                                                    荐

      6

      性能数据

      最后我们提供一下安居拍房App集成的一些性能数据,这个也是很多开发者关心的话题。后续Fair团队会提供,Fair与MXFlutter和Kraken的数据对比,敬请关后续的《Flutter动态化项目评测》。

      6.1 测试环境和功能

      Android

      荣耀 v40 Android 10, 内存 8G

      iOS

      iPhoneXSMax,iOS 13.3, 内存 4G;

      Flutter 引擎版本

      1.17.3

      测试界面

      首页混合动态列表(如首页列表动态Item图)

      6.2 包体积

      Android

      增大了13.2M。(我们默认使用两个常用的SO库v7a和v8a,如果只是用一个或者更多数据会有变化)

      iOS

      净增5.6M(arm64+armV7)

      6.3 内存

      因为安居拍房是混合开发的App,我们直接从集成Fair打包成AAR或者Farmework集成到原生后,通过Android Studio Profile 和Xcode Instruments 直接观察。

      Android

      净增20M

      iOS

      净增17.9M

      6.4 启动时间

      获取启动时间,我们并没有直接通过Dev Tools取直接获取数据,而是通过录屏截取从点击进入页面数据完整渲染之间的时间。

      Android

      净增0.05秒

      iOS

      净增0.1秒

      6.5 帧率

      界面加载完成后,在动态界面前后,快速滑动获取的数据,我们在Flutter环境时通过Dev Tools获取的数据。

      Android

      可忽略不计

      iOS

      可忽略不计


      7

      总结

      安居拍房App 通过集成Fair获取了动态化的能力,目前项目已经上线并处理了几次小场景的动态化需求。在集成Fair后,建议大家能及时梳理出后续可能使用的动态化能力,比如常用的网络、权限、存储和图片选择等等,以免在使用时发现没有适配支持。Fair直接提供Widget级的动态化,无论在完整或者部分界面动态化使用场景都具备灵活性,建议大家使用。

      有奖互动

      Perseverance Prevails

      关于 Fair在安居客拍房App中的实践 有任何疑问或想法 欢迎在评论区留言
      我们将选取5~10条留言送出58精美周边——58帮帮手机支架
      同时项目成员将从中挑选出1~3条精华留言
      精华留言将额外获得 ¥109元天猫精灵硬糖智能蓝牙音响

      点击阅读原文链接直接进入Github

      请为我们点亮star吧!

      本文分享自微信公众号 – 58技术(architects_58)。
      如有侵权,请联系 support@oschina.cn 删除。
      本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

      请登录之后再进行评论

      登录

      手机阅读天地(APP)

      • 微信公众号
      • 微信小程序
      • 安卓APP
      手机浏览,惊喜多多
      匿名树洞,说我想说!
      问答悬赏,VIP可见!
      密码可见,回复可见!
      即时聊天、群聊互动!
      宠物孵化,赠送礼物!
      动态像框,专属头衔!
      挑战/抽奖,金币送不停!
      赶紧体会下,不会让你失望!
    • 实时动态
    • 签到
    • 做任务
    • 发表内容
    • 偏好设置
    • 到底部
    • 帖子间隔 侧栏位置: