在经过了近两个月的版本迭代后,Flutter 官方在昨天发布了Flutter 2.5版本。根据官方的介绍,这是一个大版本更新,一共关闭了 4600 个问题,从 252 个贡献者和 216 个审阅者合并了 3932 个 PR。
此版本延续了一些重要的性能和工具改进,同时又发布了一些新功能,包括:
此版本带来了多项性能改进。
( #25644 ) 此列表中的第一个 PR ,主要用于从离线训练运行中连接 Metal 着色器预编译,它将最坏情况的帧光栅化时间减少了 2/3 秒,将第 99 个百分位帧减少了一半。然而着色器预热只是卡顿的来源之一,在之前的版本处理来自网络、文件系统、插件或其他 isolate 的异步事件都可能会中断动画,这是另一个卡顿的来源。
( #25789)本版本中对 UI isolate 的事件循环的调度策略( #25789)进行了改进,现在帧处理优先于其他异步事件的处理,从而在测试中消除了此问题产生的卡顿。
另一个导致卡顿的原因是垃圾收集器 (GC) 暂停 UI 线程以回收内存。以前某些图像的内存在响应 Dart VM 的 GC 执行时会延迟回收,作为早期版本中的解决方法,Flutter 引擎会通过 Dart VM 的 GC 回收暗示图像内存可以回收,这在理论上可以实现了更及时的内存回收。不幸的是这也导致了太多的主要 GC,并且有时仍然无法足够快地回收内存。
因此,在此版本中,(#26219、#82883、#84740)解决了未使用的图像的内存没有被急切地回收的问题,大大降低了了VM的GC问题。
例如,在下面的测试中,播放 20 秒动画 GIF 从需要 400 多次 GC 变为只需要 4 次。更少的主要 GC 意味着涉及图像出现和消失的动画将减少卡顿,并消耗更少的 CPU 和功率。
Flutter 2.5 的另一个性能改进是在 Dart 和 Objective-C/Swift (iOS) 或 Dart 和 Java/Kotlin (Android) 之间发送消息时的延迟。
通常,作为消息传递的一部分,从消息编解码器中删除不必要的副本可将延迟减少高达 50%,不过具体数据取决于消息大小和设备(#25988,#26331)。
并且,对于 iOS 用户而言,此版本带来了一项重大的更新,即在 Apple Silicon M1 Mac 上构建的 Flutter 应用程序也可以在 ARM iOS 模拟器 (#85642 ) 上运行。
这意味着 Intel x86_64 指令和 ARM 之间没有 Rosetta 转换,从而提高你的 iOS 应用程序测试期间的性能,并允许你避免一些微妙的 Rosetta 问题(#74970、#79641),这是全面支持 Flutter的苹果开发方面又进一步。
此版本的 Flutter和Dart 2.14是一起发布的。
新版本的Dart 带有新的格式,使级联更加清晰;新的 pub 支持忽略文件,以及新的语言功能,包括三重移位运算符的回归。此外,Dart 2.14 创建了一组标准的 lint,在新的 Dart 和 Flutter 项目之间共享,开箱即用。
从(#81303) 开始, 我们修复了 Android 一系列与全屏模式相关的问题,此更改还添加了一种在其他模式下收听全屏更改的方法。例如,用户与应用互动时,当系统 UI 返回时,开发人员现在可以编写代码在返回全屏时执行其他操作。
在此版本中,我们对新 Material You(又名 v3)的规范增加了支持,包括对浮动操作按钮大小和主题的更新(#86441),在MaterialState.scrolledUnder 可以使用 Demo 中的示例代码查看的新状态 PR 式例 ( #79999 )。
另一个改进是添加了 scroll metrics notifications(#85221、#85499),即使用户没有滚动,它也会提供可滚动区域的提示。例如,下面显示了 ListView 根据的列表的大小显示滚动条。
在这种情况下不必编写任何代码,但如果想捕获 ScrollMetricNotification 更改,则可以通过捕获此监听来完成。
另一个出色的社区贡献是为 ScaffoldMessenger , 你可能还记得 从Flutter 2.0 开始 ScaffoldMessenger 提供了一个更强大的方式来显示 SnackBars , 在屏幕的底部为用户提供通知。现在,从 Flutter 2.5 开始,我们可以在 Scaffold 的顶部添加一个横幅,该横幅会一直保持到用户关闭它为止。
我们可以通过调用 showMaterialBanner() 方法来获得此行为的ScaffoldMessenger,如下所示。
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('The MaterialBanner is below'),
),
body: Center(
child: ElevatedButton(
child: const Text('Show MaterialBanner'),
onPressed: () => ScaffoldMessenger.of(context).showMaterialBanner(
MaterialBanner(
content: const Text('Hello, I am a Material Banner'),
leading: const Icon(Icons.info),
backgroundColor: Colors.yellow,
actions: [
TextButton(
child: const Text('Dismiss'),
onPressed: () => ScaffoldMessenger.of(context)
.hideCurrentMaterialBanner(),
),
],
),
),
),
),
);
}
Material 指南规定 ,Flutter的横幅一次只能显示一个,如果要显示多次,那么就需要调用多次 showMaterialBanner、ScaffoldMessenger ,兵手动维护一个队列,在前一个横幅已被关闭之后,再显示一个新横幅。
同时,在此版本中,我们添加了文本编辑键盘快捷键可覆盖的功能( #85381),这是在 Flutter 2.0 及其新的文本编辑功能的基础上的进一步优化。例如,我们可以文本选择以及能够在处理键盘事件后停止它的事件传播。
DefaultTextEditingShortcuts 类包含每个平台上受支持的键盘快捷键列表,如果开发者想覆盖任何内容,可以使用 Flutter 的现有 Shortcuts 将任何快捷方式重新映射到现有或自定义意图,使用参考:DefaultTextEditingShortcuts。
新版本对相机插件、图像选择器插件进行了升级和优化,重点解决如下问题:
image_picker 插件也做了很多优化,提升了端到端的相机体验。
经过上面的优化,改进了 Android 的相机和 image_picker 插件的功能和稳健性。同时,在 Web 上查看相机预览、拍照、使用闪光灯和缩放控件提供基本支持,不过目前还不是被认可的插件,因此开发者需要明确添加它以在才能在 Web 中使用。
在此版本的 Flutter 中,Flutter 团队提供的每个相应插件都带有类似 【Battery】的提示,用于表示插件是否过时。如果这些插件被标识为【Battery】,那么我们不再被积极维护,我们建议使用以下插件的 plus 版本:
此次, DevTools 中增加利用引擎更新的支持(#26205、#26233、#26237、#26970、#27074、#26617)。
现在,使用DevTools,我们可以更好地将跟踪事件与特定框架相关联,这有助于开发人员在出现问题后分析问题产生的原因。
借助DevTools,我们可以Frames图表中看到页面被渲染的完整渲染过程,并且可以在应用程序呈现时填充到此图表中,从此图表中选择一个帧就可以导航到该帧的时间线事件,我们可以使用这些事件来帮助诊断应用程序中的着色器编译卡顿问题。
DevTools 会检测何时因着色器编译丢失帧,以便可以解决卡顿问题。这和之前使用DevTools进行内存分析的步骤是基本类似的。
此外,在跟踪应用程序中的 CPU 性能问题时,可能会被来自 Dart 和 Flutter 库或引擎本机代码的分析数据淹没,如果想关闭其他干扰,只专注于您自己的代码,您可以使用新的 CPU Profiler 功能( #3236) 来实现,该功能可以从这些来源中隐藏分析器信息。
对于没有过滤掉的任何类别,它们现在已经进行了颜色编码(#3310、#3324),便可以轻松查看 CPU 帧图表来自系统的哪些部分。彩色框架图,用于识别应用中的应用、原生、Dart 和 Flutter 代码活动。
同时,此版本的 DevTools 附带了对 Widget Inspector 的更新,允许将鼠标悬停在 Widget 来获取评估对象、视图属性、小部件状态等信息。
并且,当选择一个 Widget 时,会自动获取 Widget 的属性。
除了新功能外, Widget Inspector 还进行了更新和优化,更新后 DevTools 调试 Flutter 应用程序也更有用。
优化和改变的内容具体表现如下几个方面:
目前,DevTools一共发了多个版本,我们也很想听听您对这些更新的使用情况和想法,下面是DevTools 新功能的完整列表:
当然,伴随着Flutter的更新,我们的 IntelliJ/Android Studio 插件在此版本中也进行了许多改进。首先,是添加了运行集成测试的能力 ( #5459 )。
集成测试是在设备上运行的整个应用程序的一种测试方式,测试的代码位于 integration_test 目录中,并使用与testWidgets() 单元测试相同的功能。
要将集成测试添加到项目,需要按照 flutter.dev 上的说明进行操作,要将测试与 IntelliJ 或 Android Studio 连接,请添加启动集成测试的运行配置并连接设备以供测试使用。然后,再启动后,运行测试,包括设置断点、步进、跳过等。
此外,Flutter 最新的 IJ/AS 插件允许查看单元测试和集成测试运行的覆盖率信息,可以从“调试”右边的按钮来查看测试覆盖率的信息。
覆盖信息会在编辑器的装订线中使用红色和绿色条进行区分,在示例程序中,第 9-13 行被测试,但第 3 和 4 行没有被测试。
最新版本还包括预览来自 pub.dev 包中使用的图标的新功能,这些包是围绕 TrueType 字体文件(#5504、#5595、#5595、#5704)构建的,就像 Material 和 Cupertino 图标支持预览一样。
要启用图标预览,您需要告诉插件您正在使用哪些软件包,settings/preferences 中有一个新的文本字段。
下面是 IJ/AS 插件的更多信息:
Flutter 的 Visual Studio Code 插件也在此版本中进行了改进和升级,并且新增了两个命令 “Dart: Add Dependency” 和 “Dart: Add Dev Dependency” (#3306, #3474)。
这些命令提供的功能类似于Jeroen Meijer 的 Pubspec Assist 插件,新命令开箱即用,并提供定期从 pub.dev 获取的包类型过滤列表。
除此之外,开发者还可能对适用于 Dart 文件的“Fix All”命令(#3445、#3469)感兴趣,并且可以一步修复所有与dart fix相同的问题。
当然,我们也可以通过添加 source.fixAll
到 editor.codeActionsOnSave
来设置保存运行时数据,也可以启用该 dart.previewVsCodeTestRunner
设置来测试运行的 Dart 和 Flutter 的相关内容。
Visual Studio Code 测试运行器看起来与当前的 Dart 和 Flutter 测试运行器略有不同,它会跨会话保留运行结果。 Visual Studio Code 测试运行器还添加了新的装订线图标,显示测试的最后状态,可以单击以运行测试(或右键单击以获取上下文菜单)。
在即将发布的版本中,现有的 Dart 和 Flutter 测试工具将被移除,以支持新的 Visual Studio Code 测试工具。
现在,调试器也进行了相应的升级优化,可以在未处理的异常上正确中断,而这些异常以前时只能被 framework 捕获 ( #17007 )。这改善了调试体验,因为调试器可以直接指向代码中出现问题的代码行。
自 Flutter 诞生以来,我们就使用Counter 作为应用的模板,它具有许多优点:
尽管如此,我们还是觉得它没有为Flutter 开发提供一个非常好的模版。因此,在此版本中,我们提供了一个新模板 ( #83530 ),创建的命令如下:
flutter create -t skeleton my_app
骨架模板生成一个遵循社区最佳实践的两页列表视图,并提供了下面的功能:
随着时间的推移,我们会继续完善新模板,直到他更好的为让想要了解它的人学习它。
另一方面,我们还升级了 Pigeon ,并发布了的 1.0 版本。Pigeon 是一个代码生成工具,用于在 Flutter 及其主机平台之间生成类型安全的互操作代码,它允许定义插件 API 的描述,并为 Dart、Java 和 Objective-C(分别可用于 Kotlin 和 Swift)生成框架代码。
目前,Flutter 团队的一些插件中已经使用了 Pigeon,在此版本中它提供了更多有用的错误消息,增加了对泛型、原始数据类型作为参数和返回类型以及多个参数的支持,预计开发者将来会更频繁地使用它。
除此之外,Flutter 2.5的重大更改和弃用还有如下一些:
此外随着 Flutter 2.5 的发布,我们将弃用2020 年 9 月宣布的对 iOS 8 的支持。放弃对市场份额不到 1% 的 iOS 8 的支持,使 Flutter 团队能够专注于更广泛使用的新平台,弃用意味着这些平台可以工作,但我们不会在这些平台上进行功能的更新和插件的支持。