Flutter 3.10 适配之单例 Window 弃用,一起来了解 View.of 和 PlatformDispatcher

news2024/9/20 16:24:15

Flutter 3.10 发布之后,大家可能注意到,在它的 release note 里提了一句: Window singleton 相关将被弃用,并且这个改动是为了支持未来多窗口的相关实现

所以这是一个为了支持多窗口的相关改进,多窗口更多是在 PC 场景下更常见,但是又需要兼容 Mobile 场景,故而有此次改动作为提前铺垫。

如下图所示,如果具体到对应的 API 场景,主要就是涉及 WidgetsBinding.instance.windowMediaQueryData.fromWindow 等接口的适配,因为 WidgetsBinding.instance.window 即将被弃用。

你可以不适配,还能跑,只是升级的技术债务往后累计而已。

那首先可能就有一个疑问,为什么会有需要直接使用 WidgetsBinding.instance.window 的使用场景?简单来说,具体可以总结为:

  • 没有 BuildContext ,不想引入 BuildContext
  • 不希望获取到的 MediaQueryData 受到所在 BuildContext 的影响,例如键盘弹起导致 padding 变化重构和受到 Scaffold 下的参数影响等

这部分详细可见:《MediaQuery 和 build 优化你不知道的秘密》 。

那么从 3.10 开始,针对 WidgetsBinding.instance.window 可以通过新的 API 方式进行兼容:

  • 如果存在 BuildContex , 可以通过 View.of 获取 FlutterView,这是官方最推荐的替代方式
  • 如果没有 BuildContex 可以通过 PlatformDispatcherviews 对象去获取

这里注意到没有,现在用的是 View.of ,获取的是 FlutterView ,对象都称呼为 View 而不是 「Window」,对应的 MediaQueryData.fromWindow API 也被弃用,修改为 MediaQueryData.fromView ,这个修改的依据在于:

起初 Flutter 假定了它只支持一个 Window 的场景,所以会有 SingletonFlutterWindow 这样的 instance window 对象存在,同时 window 属性又提供了许多和窗口本身无关的功能,在多窗口逻辑下会显得很另类。

那么接下来就让我们用「长篇大论」来简单介绍下这两个场景的特别之处。

存在 BuildContext

回归到本次的调整,首先是存在 BuildContext 的场景,如下代码所示,对于存在 BuildContex 的场景, View.of 相关的调整为:

/// 3.10 之前
double dpr = WidgetsBinding.instance.window.devicePixelRatio;
Locale locale = WidgetsBinding.instance.window.locale;
double width =
    MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width;


/// 3.10 之后
double dpr = View.of(context).devicePixelRatio;
Locale locale = View.of(context).platformDispatcher.locale;
double width =
    MediaQueryData.fromView(View.of(context)).size.width;

可以看到,这里的 View 内部实现肯定是有一个 InheritedWidget ,它将 FlutterView 通过 BuildContext 往下共享,从而提供类似 「window」 的参数能力,而通过 View.of 获取的参数:

  • FlutterView 本身的属性值发生变化时,是不会通知绑定的 context 更新,这个行为类似于之前的 WidgetsBinding.instance.window
  • 只有当 FlutterView 本身发生变化时,比如 context 绘制到不同的 FlutterView 时,才会触发对应绑定的 context 更新

可以看到 View.of 这个行为考虑的是「多 FlutterView」 下的更新场景,如果是需要绑定到具体对应参数的变动更新,如 size 等,还是要通过以前的 MediaQuery.of / MediaQuery.maybeOf 来实现。

而对于 View 来说,每个 FlutterView 都必须是独立且唯一的,在一个 Widget Tree 里,一个 FlutterView 只能和一个 View 相关联,这个主要体现在 FlutterView 标识 GlobalObjectKey 的实现上。

简单总结一下:在存在 BuildContex 的场景,可以简单将 WidgetsBinding.instance.window 替换为 View.of(context) ,不用担心绑定了 context 导致重构,因为 View.of 只对 FlutterView 切换的场景生效

不存在 BuildContext

对于不存在或者不方便使用 BuildContext 的场景,官方提供了 PlatformDispatcher.views API 来进行支持,不过因为 get views 对应的是 Mapvalues ,它是一个 Iterable 对象,那么对于 3.10 我们需要如何使用 PlatformDispatcher.views 来适配没有 BuildContextWidgetsBinding.instance.window 场面

PlatformDispatcher 内部的 views 维护了中所有可用 FlutterView 的列表,用于提供在没有 BuildContext 的情况下访问视图的支持。

你说什么情况下会有没有 BuildContext ?比如 Flutter 里 的 runApp ,如下图所示,3.10 目前在 runApp 时会通过 platformDispatcher.implicitView 来塞进去一个默认的 FlutterView

implicitView 又是什么?其实 implicitView 就是 PlatformDispatcher._views 里 id 为 0 的 FlutterView ,默认也是 views 这个 Iterable 里的 first 对象。

也就是在没有 BuildContext 的场景, 可以通过 platformDispatcher.views.first 的实现迁移对应的 instance.window 实现。

/// 3.10 之前
MediaQueryData.fromWindow(WidgetsBinding.instance.window)
/// 3.10 之后
MediaQueryData.fromView(WidgetsBinding.instance.platformDispatcher.views.first)

为什么不直接使用 implicitView 对象? 因为 implicitView 目前是一个过渡性方案,官方希望在多视图的场景下不应该始终存在 implicit view 的概念,而是应用自己应该主动请求创建一个窗口,去提供一个视图进行绘制。

所以对于 implicitView 目前官方提供了 _implicitViewEnabled 函数,后续可以通过可配置位来控制引擎是否支持 implicitView ,也就是 implicitView 在后续更新随时可能为 null ,这也是我们不应该在外部去使用它的理由,同时它是在 runApp 时配置的,所以它在应用启动运行后永远不会改变,如果它在启动时为空,则它永远都会是 null。

PlatformDispatcher.instance.views[0] 在之前的单视图场景中,无论是否有窗口存在,类似的 implicitView 会始终存在;而在多窗口场景下,PlatformDispatcher.instance.views 将会跟随窗口变化。

另外我们是通过 WidgetsBinding.instance.platformDispatcher.views 去访问 views ,而不是直接通过 PlatformDispatcher.instance.views ,因为通常官方更建议在 Binding 的依赖关系下去访问 PlatformDispatcher

除了需要在 runApp() 或者 ensureInitialized() 之前访问 PlatformDispatcher 的场景。

另外,如下图所示,通过 Engine 里对于 window 部分代码的实现,可以看到我们所需的默认 FlutterView 是 id 为 0 的相关依据,所以这也是我们通过 WidgetsBinding.instance.platformDispatcher.views 去兼容支持的逻辑所在。

最后

最后总结一下,说了那么多,其实不外乎就是将 WidgetsBinding.instance.window 替换为 View.of(context) ,如果还有一些骚操作场景,可以使用 WidgetsBinding.instance.platformDispatcher.views ,如果不怕后续又坑,甚至可以直接使用 WidgetsBinding.instance.platformDispatcher.implicitView

整体上解释那么多,主要还是给大家对这次变动有一个背景认知,同时也对未来多窗口实现进展有进一步的了解,相信下一个版本多窗口应该就可以和大家见面了。

更多讨论可见:

  • https://github.com/flutter/flutter/issues/120306
  • https://github.com/flutter/engine/pull/39553
  • https://github.com/flutter/flutter/issues/116929
  • https://github.com/flutter/flutter/issues/99500
  • https://github.com/flutter/engine/pull/39788

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/536559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

统计学习方法:序贯概率比检验SPRT

Sequential Probability Ratio Test 应用:制造过程中的质量控制和医学试验中的异常检测 1.theory/principal 区别(vs固定样本检验):在固定样本检验中,一定数量的观察结果被用来从两个或多个备选方案中选择一个假设。而SPRT则是一次检查一个…

AI“应用商店”来了!OpenAI首批70个ChatGPT Plugin最全梳理

OpenAI放出大招,本周将向所有ChatGPT Plus用户开放联网功能和众多插件本周将向所有ChatGPT Plus用户开放联网功能和众多插件,允许ChatGPT访问互联网并使用70个第三方插件。 本批第三方插件能够全方位覆盖衣食住行、社交、工作以及学习等日常所需&#x…

Electron自定义窗口

Electron标题栏隐藏和自定义 Electron应用自定义标题栏样式 标题栏样式允许隐藏浏览器窗口的大部分色彩,同时保持系统原生窗口控件完整无损,并可以在 BrowserWindow 的构造器中使用 titleBarStyle 选项来配置。 应用 hidden 标题栏样式的结果是隐藏标…

无线充+台灯专用PD诱骗芯片LDR6328S

近几年,日常生活中到处可以看到消费者使用支持Type-c接口的电子产品,如手机,笔记本,筋膜枪,蓝牙音箱等等。例如,像筋膜枪,蓝牙音箱,无人机,小风扇。 无线充台灯方案&…

librosa语音信号处理

librosa是一个非常强大的python语音信号处理的第三方库,本文参考的是librosa的官方文档,本文主要总结了一些重要,对我来说非常常用的功能。学会librosa后再也不用python去实现那些复杂的算法了,只需要一句语句就能轻松实现。 先总…

数字化时代,初创公司如何建设业财一体化

业财一体的关键是构建“业务活动跟财务活动之间的线上化链接”,财务可以通过线上支撑业务,业务活动数据可以通过线上高时效触达财务;从业务数据到财务数据,除了需要运营系统的支撑还需要会计引擎的实现,会计引擎将业务…

优秀的开发者,如何借助免费低代码平台实现数据采集?

采集和管理数据, 从未如此简单自然 一款免费的零代码产品‘敲敲云’,可以帮助每个人轻松创建表单,自由收集问卷样本、活动参与者名单、客户数据,原本几天的工作在 1 个小时内轻松搞定。 表单编辑器,让你和数据专家一样…

分享5款高效率软件,免费无广告

人类与99%的动物之间最大差别在于是否会运用工具,借助好的工具,能提升几倍的工作效率。 1.多设备键鼠共享——Synergy Synergy让你可以轻松地在办公桌上多台计算机之间共享你的鼠标和键盘。你只要将鼠标(指针)从一台计算机的屏幕…

用小程序技术服务数字城市

“十四五”规划大纲明确指出,要迎接数字时代,激活数据要素潜力,加快建设网络强国,加快建设数字经济、数码社会和数码政府,以数字化转型为变革的方式改变生产方式、生活方式和治理。 数字城市的技术内涵 数字城市的发…

轨道交通信号安全完整性等级(SIL)

轨道交通行业中,对于信号系统、车辆子系统等安全相关的系统有安全完整性(SIL)等级的要求,需要进行通用产品层安全评估和工程特定应用项目安全评估,已经形成了行业共识。对于初次了解SIL的人,在实际应用中存…

一文告诉你:为什么小程序更安全

随着数字时代的到来,数据不再是普通的符号和徽标,也不仅仅是普通的计算和统计工具。而安全问题也已经成为了一个非常重要的议题。今天就来探讨下小程序的安全架构,以了解小程序如何做到安全保障。 小程序的安全架构 先说说小程序自身的安全架…

【C++】YY带你手把手掌握C++系列 (P2)未完结

前言 大家好,这里是YY的带你手把手掌握C系列。大部分知识点都含有【特性介绍】【使用场景】【注意要点】【易混淆点】【代码演示】【画图演示】由于C体系之庞大,所以该系列以分P形式更新!本篇博客为P2! 大家可以通过本篇博客查找C…

【jmeter】同一线程组下多个请求分别执行不同次数

今天介绍下JMeter如何控制请求执行次数 主要有两种方式: 方式一:通过循环控制器控制每个请求的执行次数 例如:脚本执行规律是这样的,login-->customerPage-->search 我想执行一遍login,然后运行3遍customerP…

智能的本质人工智能与机器人领域的64个大问题阅读笔记(3)

目录 哥德尔不完备定理是什么? 文件重命名的快捷键 第一个质疑这类言论的哲学家是休伯特德雷福斯 (HubertDreyfus),他在《Alchemy and Artifcial Intelligence》(1965)一书中写道:“人工智能的长足发展......必须有待于全新计算机的问世。现有的计算机…

数据结构-算法时间复杂度

1.算法的时间复杂度取决于一段程序中基本运算的频度 2.基础规则 1.加法:O(n) O(max(F(n),G(n)) 2.乘法:O(n) O(F(n)*G(n)) 3.取基本运算中n增长最快的项:F(n) anbncn 时间复杂度为O(n) 3. 例子 接下来举几个例子…

chatgpt与其他行业的结合

chatgpt的应用场景非常广泛,其中一些主要应用场景包括以下几个方面: 1. 自然语言处理:chatgpt作为一种强大的机器学习算法,在自然语言处理领域得到了广泛应用。例如,它可以用来完成机器翻译、情感分析、文本分类等任务…

C语言的标准演变及编程机制

目录 C语言的标准 K&R C C89 C90 C99 C11 C18 C2x C语言的编程机制 示例 1.预处理(Preprocessing) 2.编译(Compilation) 3.汇编(Assemble) 4.链接(Linking) 结语 参考文献 C语言的标准 c语言标准的发展主要分为以下几个阶段: K&R C 1978…

【C++】类的属性和行为

欢迎来到博主 Apeiron 的博客,祝您旅程愉快 !时止则止,时行则行。动静不失其时,其道光明。 目录 1、缘起 2、封装 3、总结 1、缘起 C 面向对象的三大特性为:封装,继承和多态。C 认为 万事万物皆为对象&a…

刷题day66:最后一块石头的重量II

题意描述&#xff1a; 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&a…