Flutter 3.10 发布之后,我们或许注意到,在它的 release note 里提了一句: Window singleton 相关将被弃用,并且这个改动是为了支撑未来多窗口的相关完成。
所以这是一个为了支撑多窗口的相关改善,多窗口更多是在 PC 场景下更常见,但是又需要兼容 Mobile 场景,故而有此次改动作为提早铺垫。
如下图所示,假如详细到对应的 API 场景,首要便是涉及 WidgetsBinding.instance.window
和 MediaQueryData.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
能够经过PlatformDispatcher
的views
目标去获取
这里注意到没有,现在用的是 View.of
,获取的是 FlutterView
,目标都称呼为 View 而不是 「Window」,对应的 MediaQueryData.fromWindow
API 也被弃用,修正为 MediaQueryData.fromView
,这个修正的依据在于:
起先 Flutter 假定了它只支撑一个 Window 的场景,所以会有
SingletonFlutterWindow
这样的 instance window 目标存在,一起window
特点又供给了许多和窗口自身无关的功用,在多窗口逻辑下会显得很另类。
那么接下来就让咱们用「长篇大论」来简略介绍下这两个场景的特别之处。
存在 BuildContext
回归到本次的调整,首要是存在 BuildContext 的场景,如下代码所示,关于存在 BuildContex
的场景, View.of
相关的调整为:
/// 3.10 之前
doubledpr=WidgetsBinding.instance.window.devicePixelRatio;
Localelocale=WidgetsBinding.instance.window.locale;
doublewidth=
MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width;
/// 3.10 之后
doubledpr=View.of(context).devicePixelRatio;
Localelocale=View.of(context).platformDispatcher.locale;
doublewidth=
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
对应的是 Map
的 values
,它是一个 Iterable
目标,那么关于 3.10 咱们需要如何运用 PlatformDispatcher.views
来适配没有 BuildContext
的 WidgetsBinding.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
。
整体上解释那么多,首要仍是给我们对这次变动有一个布景认知,一起也对未来多窗口完成进展有进一步的了解,信任下一个版本多窗口应该就能够和我们碰头了。
更多评论可见:
- github.com/flutter/flu…
- github.com/flutter/eng…
- github.com/flutter/flu…
- github.com/flutter/flu…
- github.com/flutter/eng…