生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

FlutterBoost3.0 发布 preview 版本

  • 2021-07-05
  • 本文字数:4086 字

    阅读完需:约 13 分钟

FlutterBoost3.0发布preview版本

在经历了近两个月的开发以及内部测试与线上灰度,FlutterBoost3.0 的 preview 版本终于与大家见面了,与 beta 版本相比,这个版本在不大动主体结构的基础上,增加了以下能力:


1.重构生命周期,确保生命周期语义准确

2.双端一致性近一步对齐

3.增加自定义的启动参数

4.实现页面返回传参方案

5.支持页面透明能力

6.增加自定义事件发送机制

7.增加前置拦截器

8.提供更完善的文档与例子


由于篇幅有限,就不对以上能力一一展开了。如果对具体实现感兴趣的话,可以通过源码和文档来了解相应的功能,我们今天先来聊一聊生命周期部分的设计与实现、文档与用例和社区建设。

页面生命周期设计

FlutterBoost3.0 有两个和页面相关的概念,一个是 BoostContainer,另一个是 BoostPage。每个 BoostContainer 在 Native 层都会有一个与之对应的容器,比如在 Android 端,这个容器可能是 FlutterBoostActivity 或者 FlutterBoostFragment,而在 iOS 端,这个容器则指的是 FBFlutterViewContainer。每个 BoostContainer 都会有一个与之对应的 Navigator,因而一个 BoostContainer 可以包含多个 BoostPage,这个设计也被我们称之为双重栈。细心的同学可能已经发现了,当我们需要打开一个 Flutter 页面时,有一个额外的参数withContainer,这个参数设置为 false 时,表示打开页面时不需要打开一个新容器,而这个参数如果被设置为 true,则会在打开页面的同时,去打开一个新容器。


null

在开发业务的过程中,我们常常需要知道一个 Flutter 页面的可见性,比如我们写了一个 Flutter 页面,里面有一个 VideoWidget,我们希望 VideoWidget 在页面可见的时候播放,在页面不可见的时候暂停。对页面可见性变化的监听是 FlutterBoost 需要提供的核心能力之一,因此我们提供了一个名为 PageVisibilityObserver 的 API,用于专门监听页面可见性变化。


在一开始的设计当中,我们是通过上层 Dart 代码来掌控页面生命周期的。我们在 FlutterBoostAppState 里,维护了一个 List<BoostContaner>,而在每个 BoostContainer 中,则维护了一个 List<BoostPage>,所以显示的页面实际上就是顶部 BoostContainer 中的顶部 BoostPage,所以每次顶部的 BoostContainer 发生变化,或者顶部 BoostContainer 中的顶部 BoostPage 发生变化,我们就认为发生了页面可见性变化,并将相应事件分发下去。


然而这个方案在实践的过程中,发现了一些问题,由于 Dart 侧只对 Flutter 的双层栈有感知,而对 Native 侧的页面栈则是毫无感知的,所以哪怕一个页面是顶部 BoostContainer 中的顶部 BoostPage,也不见得这个页面就处于显示状态。举个例子,比如 Flutter 页面 A 去打开一个 Native 页面 B,那么在打开 Native 页面 B 之后,Flutter 页面 A 还是在双重栈顶部,因此如果不做任何处理,那么 FlutterBoost 还是认为 Flutter 页面 A 是可见的。我们也尝试了一些手段去解决这些 Bad Case,比如在 Native 层也维护一个 Flutter 页面栈用来感知页面显示隐藏等。但是在后续的验证过程中,我们发现这个方案可维护性不高,最终放弃了。


之后我们决定还是采用更稳妥的方案,BoostContainer 的显示和隐藏,让 Native 容器自己来控制,当 Native 容器展示的时候发出 onContainerShow 事件通知对应的 BoostContainer 展示,Native 容器隐藏时再发出 onContainerHide 事件通知对应的的 BoostContainer 隐藏,这样生命周期难以维护的问题也就解决了,这个方案的可维护性相比上一个方案要稳定,但是这个方案也有一个不得不解决的问题,第一次 onContainerShow 可能会收不到。我们以 Android 为例,FlutterBoostActivity 创建后的第一次 onResume 发出了 onContainerShow 事件,然而该事件并不一定会被收到,因为此时可能页面对应的 Widget 还没有完成创建。稳定的生命周期事件是一个强诉求,所以这个问题我们需要在 FlutterBoost3.0 彻底解决。那么这个问题该如何解决呢?为了解决这个问题,我们将第一次收到 onContainerShow 事件单独处理,具体逻辑如下:


    assert(id != null);    if (!hasShownPageIds.contains(id)) {        hasShownPageIds.add(id);
// This case indicates it is the first time that this container show // So we should dispatch event using // PageVisibilityBinding.dispatchPageShowEventOnPageShowFirstTime // to ensure the page will receive callback PageVisibilityBinding.instance .dispatchPageShowEventOnPageShowFirstTime(container.topPage.route); } else { PageVisibilityBinding.instance .dispatchPageShowEvent(container.topPage.route); }}
复制代码


而在 PageVisibilityBinding.dispatchPageShowEventOnPageShowFirstTime 中,我们将事件分发延迟到这一帧渲染结束。


///When page show first time,we should dispatch event in [FrameCallback]///to avoid the page can't receive the show eventvoid dispatchPageShowEventOnPageShowFirstTime(Route<dynamic> route) {    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {        dispatchPageShowEvent(route);    });}
复制代码


这样我们就能确保第一次 onContainerShow 事件能够被接收到。从最后的代码来看,这是一个微不足道的改动,但是从设计上看,这个改动明确定义了页面生命周期事件,确保了生命周期事件一定被调用到。

Flutter 应用生命周期设计

对于纯 Flutter 应用来说,一个 Flutter 应用实际上是跑在一个 Activity 或者 ViewController 上的,所以 Flutter 应用的生命周期实际上也和 Activity 或 ViewController 的生命周期绑定了,这也是 Flutter 目前的实现。但是对于单引擎多页面的混合栈场景来说,这无疑是不适用的。如果我们不对 Flutter 应用生命周期进行任何处理,那么就有可能出现 Flutter 应用生命周期混乱,最终导致界面无法刷帧。之前我们解决这个问题的思路,都是从 Native 层出发,通过控制生命周期事件的发送,来校正 Flutter 应用的生命周期。比如 Android 端,就是在每次 Flutter 应用被 pause 的时候,补发一个 resume 事件,而 iOS 端则是绕过 FlutterViewController 生命周期方法来自行管理生命周期事件。这样做虽然校正了 Flutter 应用的生命周期,但最终也导致了上层应用的生命周期非常混乱,可能会出现 pause 和 resume 连续多次被调用的情况。


为了上层使用者能有一个稳定的 Flutter 应用生命周期,我们决定将这部分能力接管。我们提供了一个 BoostFlutterBinding,用于接管生命周期,相关代码如下


mixin BoostFlutterBinding on WidgetsFlutterBinding {
bool _appLifecycleStateLocked = true;
@override void initInstances() { super.initInstances(); _instance = this; changeAppLifecycleState(AppLifecycleState.resumed); }
static BoostFlutterBinding get instance => _instance; static BoostFlutterBinding _instance;
@override void handleAppLifecycleStateChanged(AppLifecycleState state) { if (_appLifecycleStateLocked) { return; } Logger.log('boost_flutter_binding: handleAppLifecycleStateChanged ${state.toString()}'); super.handleAppLifecycleStateChanged(state); }
void changeAppLifecycleState(AppLifecycleState state) { if (SchedulerBinding.instance.lifecycleState == state) { return; } _appLifecycleStateLocked = false; handleAppLifecycleStateChanged(state); _appLifecycleStateLocked = true; }}
复制代码


代码非常简单,就是将 handleAppLifecycleStateChanged 方法给 hook 掉,这样无论 Native 层如何调用 Flutter 设定的生命周期事件,都不会影响到上层 Flutter 应用的生命周期。另外我们提供了一个 changeAppLifecycleState 方法,这个方法可以真正来改变上层 Flutter 应用的生命周期,目前这个方法的调用时机与 Flutter 容器个数相关,当容器大于等于 1,Flutter 应用的生命周期状态为 resumed,而容器个数为 0 时,Flutter 应用的生命周期状态则为 paused。

文档与用例完善

FlutterBoost 在之前只有一份接入文档,这对使用者来说并不算友好。因此我们决定提供更完善的文档。我们梳理了大家最关心的几个主题:

• 集成详细步骤

• 基本的路由 API

• 页面生命周期监测相关 API

• 自定义发送跨端事件 API


对于这些主题,我们这次都提供了相对应的文档,让使用者接入 FlutterBoost 可以更轻松,在遇到问题的时候也能更容易排查。另外我们也正在编写全新的 example3.0,配合文档使用,在这个新的 example3.0 中,我们会把所有文档中提到的部分都以用例的方式呈现出来,希望这能帮助到大家。

社区建设

之后 Boost 所有的开发计划工作,都会在 project 看板上体现出来,对应的地址为( https://github.com/alibaba/flutter_boost/projects)。对我们工作感兴趣的同学,可以在看板上看到我们的工作规划,欢迎一起交流探讨。另外如果有哪些想要我们支持的 feature,也可以提 issue 给我们,如果我们评估合理,也会加入到看板上。


null


于此同时,我们增加了一个 AUTHORS 文件(https://github.com/alibaba/flutter_boost/blob/master/AUTHORS),记录所有 FlutterBoost 的贡献者(Contributors)。之后给我们提 PR 的同学,在提供 PR 的同时,也可以在这个文件上,加上你的名字,感谢大家为 Boost 做出的贡献。

未来展望

FlutterBoost3.0 作为 AliFlutter 的核心基础设施,目前主要由闲鱼团队和 UC Hummer 团队进行开发维护,主要开发者包括 noborder、0xZOne、christyuj、ColdPaleLight、luckysmg,另外也要感谢 seedotlee、CheungSKei、bktoky、jk 等同学为 FlutterBoost3.0 做出的贡献,目前集团内已有多个 App 接入了 FlutterBoost3.0,包括夸克、淘宝联盟、吃货笔记等。


之后 FlutterBoost3.0 的 preview 版本原则上不会再做 Breaking Change,目前已经使用了 beta 版的同学,也可以陆续切到 preview 版本上了,下个阶段我们会将工作重心放在 issue 收敛与文档用例补齐上。

FlutterBoost 作为一个开源项目,还有很长的路要走,感谢大家一路支持和包容,我们也希望有更多同学能参与到这个项目中来。


本文转载自:闲鱼技术(ID:XYtech_Alibaba)

原文链接:FlutterBoost3.0发布preview版本

2021-07-05 08:002928

评论 1 条评论

发布
用户头像
有兴趣卖解决方案吗,关于移动端的,我们是华东院的
2021-09-17 13:51
回复
没有更多了
发现更多内容

【直播】开发者手机切换4.1总结

Laval小助手

【论文速读】| 对大语言模型解决攻击性安全挑战的实证评估

云起无垠

数字人直播系统源码是什么?可一次性买断交付吗?

青否数字人

数字人

DevOps迈向标准化,平台工程让开发运维更轻松

SEAL安全

DevOps 运维 平台工程

系统开发常用的技术栈有什么?

这我可不懂

Macs Fan Control Pro 如何控制风扇速度?Macs Fan Control Pro使用教程及安装包分享

Rose

Macs Fan Control Pro下载 Macs Fan Control Pro破解 Mac 电脑风扇速度 Macs Fan Control 教程

如何用Flask中的Blueprints构建大型Web应用

华为云开发者联盟

Python 开发 华为云 Web应用 华为云开发者联盟

PostgreSQL数据迁移至Doris:一站式解决方案

NineData

postgresql Doris 实时数据分析 实时同步 NineData

VMware Fusion Pro 13许可证密钥 VM虚拟机如何使用?

Rose

VM虚拟机密钥 VMware Fusion Pro 13密钥 mac虚拟机软件

软通咨询携手普元电力,共绘企业规范化管理与人才发展新篇章

软通咨询

数字化转型 绩效管理 数字化咨询 数据智能 数字化咨询

基于vite多页面实现多端同构开发和部署

京东科技开发者

大文件上传实践分享

京东科技开发者

青否数字人直播系统源码级交付私有化部署方案来了!

青否数字人

数字人

实战篇-Docker 安装ELK(单节点)

派大星

运维监控 ELK Stack

2022全球AI生物智药大赛赛道二参赛攻略@paipai

阿里云天池

阿里云

鸿蒙实训营火爆北京,政企民生、金融、出行等领域的百余家企业积极参与!

最新动态

WiFi7 technology: IPQ9574 and QCN9274/QCN6274 combine to create the next generation of wireless networks

wifi6-yiyi

ipq9574

AI时代来临我们要如何面对?

小齐写代码

自定义对象池实践

FunTester

软件测试学习笔记丨Allure2 报告中添加附件(html)应用场景

测试人

软件测试

手把手带你用香橙派AIpro开发AI推理应用

华为云开发者联盟

华为云 昇腾 华为云开发者联盟 香橙派AIpro AI推理应用

CQ 社区版2.10.0 | 新增 SQL 审核、全新英文版上线…

BinTools图尔兹

mongodb mongo 数据库管理 SQL审核 SQLite编辑器

reduce函数20个高级用法 看看你掌握了多少?

高端章鱼哥

Remote Desktop Manager for mac(远程桌面管理器)v2024.1.6.2中文激活版

影影绰绰一往直前

网络延迟对事务的影响

GreatSQL

延迟 网络 事务 greatsql

AI数字人短视频制作神器来啦!

青否数字人

数字人

案例研究:如何通过淘宝天猫商品销量数据分析竞争对手

tbapi

淘宝API接口 淘宝商品销量数据接口

是什么阻碍了你的成长

老张

个人成长 职场成长

百川仓配切量接口成长史

京东科技开发者

学算法要读《算法导论》吗?

京东科技开发者

最新 Apifox 3 月更新:详解多分支升级、Query 参数支持枚举、自定义快捷键

Apifox

程序员 Apifox API 接口工具 API 工具

FlutterBoost3.0发布preview版本_大前端_闲鱼技术_InfoQ精选文章