写点什么

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:003606

评论 1 条评论

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

【体验有奖】5 分钟函数计算部署 AI 艺术字应用,晒姓氏头像赢 Cherry 键盘!

阿里巴巴云原生

阿里云 Serverless 云原生 函数计算

TuGraph Analytics图数据集成:表到图的最后一公里

TuGraphAnalytics

数据仓库 数据集成 tugraph 图数据集成 图表转换

释放云算力 繁荣云生态,12 位技术专家解读智算时代下的云计算 | 附PPT下载

OpenAnolis小助手

centos 阿里云 操作系统 龙蜥社区 分论坛

技术浅析:前端沙箱数据安全保护的机制

FN0

沙箱 小程序安全沙箱

业界声音|PolarDB最值得关注的技术创新有哪些?

阿里云瑶池数据库

数据库 云计算 阿里云 云原生 polarDB

EMQ 和 Intel 评选工业物联网领域最佳案例与应用

新消费日报

【京东云新品发布月刊】2024年1月产品动态

京东科技开发者

NFT Dapp的兴起:关于创建NFT Dapp需要了解什么

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

软件测试学习笔记丨常用的设备交互命令

测试人

软件测试

2024年的Rust与Go,看完你悟了吗?

伤感汤姆布利柏

EMQ 和 Intel 评选工业物联网领域最佳案例与应用

新消费日报

SD-WAN和专线混合组网:企业出海网络解决方案

Ogcloud

SD-WAN SD-WAN组网 SD-WAN服务商

年货零食大单来袭,极兔速递如何精准破解旺季物流难题?

新消费日报

评估SD-WAN的三个功能

Ogcloud

SD-WAN SD-WAN组网 SD-WAN服务商

【技术探讨】一种多节点5Km(1.2M bps速率)实时Sub-G无线通信的物联网通讯解决方案

Geek_ab1536

鱼和熊掌如何兼得?一文解析RDS数据库存储架构升级

阿里云瑶池数据库

数据库 云计算 阿里云 云原生 polarDB

语音数据集在智能驾驶中的价值与应用

数据堂

金蝶云星辰与交通银行的完美结合:引领企业迈向高效支付管理新时代!

聚道云软件连接器

案例分享

A/B实验在字节跳动推荐系统中的应用与实践

字节跳动数据平台

数据库 大数据 AB实验 企业号 1 月 PK 榜 数字化增长

对于企业来讲鸿蒙是机会还是累赘?

FN0

鸿蒙系统 鸿蒙 Ability

解锁淘宝商品详情数据:淘宝天猫商品详情接口助你精准营销

tbapi

淘宝商品详情数据接口 淘宝API接口 天猫商品详情数据接口 淘宝商品数据接口

SD-WAN技术:网络升级的智慧选择

Ogcloud

SD-WAN SD-WAN组网 SD-WAN服务商

选300平米别墅还是90平米小平层?一文带你读懂PolarDB分布式版集分一体化

阿里云瑶池数据库

数据库 云计算 阿里云 polarDB

软件测试学习笔记丨自动化关键数据记录

测试人

软件测试 测试开发

Hover的“Project Lever”为Kava带来实质收益

股市老人

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