速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

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

评论 1 条评论

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

大数据培训flink窗口(Windows)的表现形式

@零度

大数据开发

技术分享| 云服务器的使用-nginx的安装及使用

anyRTC开发者

nginx centos 音视频 服务器

InfoQ 极客传媒 15 周年庆征文|手摸手教你在Windows安装Docker,一定要看到最后

迷彩

Docker 架构 运维 6月月更 InfoQ极客传媒15周年庆

如何制定业务的故障分级标准?

华仔

架构实战营 故障定级 故障分级

Vue-10-class的动态绑定

Python研究所

6月月更

千亿参数“一口闷”?大模型训练必备四种策略

OneFlow

人工智能 模型训练 策略

WebStorm注册码_WebStorm2022年激活永久实测有效

Geek_75f9e9

webstorm

天翼云数据中台通过“数字政府智慧中台”评估

Geek_2d6073

深度合作 | TDengine + 华为云 Stack 强强联合打造高效物联网时序数据处理解决方案

TDengine

数据库 tdengine 时序数据库

【直播回顾】战码先锋第五期:深入理解OpenHarmony系统启动,轻松踏上设备软件开发之旅

OpenHarmony开发者

Open Harmony

还不知道npm私服?一篇教会你搭建私服并发布vue3组件库到nexus

Jianmu

ci 前端 npm Vue3 私服

开课报名|「Takin开源特训营」第一期来啦!手把手教你搞定全链路压测!

TakinTalks稳定性社区

开源 全链路压测 生产环境全链路压测 安全生产 稳定性保障

莫把暑假插错秧,代码哪有足球香,Alluxio足球青训营在线摇人!

Alluxio

微软 开源 足球 分布式, CCF开源高校行

二级等保要求几年做一次测评?测评项目有多少项?

行云管家

等级保护 等保测评 二级等保 等保二级

Java—线程安全II

武师叔

6月月更

【云计算】云计算平台是什么意思?可以划分为哪三类?

行云管家

云计算 云服务 私有云 云平台 云计算平台

十分钟带你入门Docker容器引擎

百思不得小赵

云原生 Docker 镜像 6月月更

一文掌握软件安全必备技术 SAST

SEAL安全

网络安全 软件安全 SAST工具 SAST

测试基础之:测试覆盖率

甜甜的白桃

软件测试 测试覆盖率 JACOCO 6月月更

洞见科技荣获「最受投资人欢迎的隐私计算服务企业」奖

洞见科技

隐私计算 数据要素

得物前端唤端业务场景和技术精讲

得物技术

前端 前端教程 等待唤醒 业务场景 前端工具

Wallys/Routerboard/DR344/WiFi/AR9344 FCC/CE/IC

wallys-wifi6

AR9344 802.11a

谈谈 JDK 和 SAPMachine 的关系

汪子熙

Java jdk jre SAP 6月月更

java编程培训Mybatis的增删改查与获取参数值

@零度

mybatis JAVA开发

谷歌AI人格觉醒“喜提”热搜,我们找清华大佬聊了聊 AI 对话系统的惊人进展

硬科技星球

人工智能 谷歌 图灵测试

NFT卡牌盲盒链游系统dapp开发搭建

薇電13242772558

智能合约 NFT

数据智能基础设施升级窗口将至?看九章云极 DingoDB 如何击破数据痛点

九章云极DataCanvas

人工智能 数据库 数据 数据智能

Go语言入门基础之库源码文件

Damon

6月月更

市值严重低估,现金15亿,百世走的路对吗?

科技新知

洞见科技当选中国信通院隐私计算联盟「副理事长+政务应用工作组组长」单位

洞见科技

隐私计算

融云首席科学家任杰:数字游民和意识体,疫情将如何影响人类社会进化

融云 RongCloud

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