Flutter 2.5 更新一览
Flutter 2.5 正式版已于上周正式发布!这是一次重要的版本更新,也是 Flutter 发布历史上各项统计数据排名第二的版本。我们关闭了 4600 个 Issue,合并了 3932 个 PR,它们分别来自 252 个贡献者和 216 个审核者。回顾去年 -- 我们收到来自 1337 个贡献者提交的 21072 个 PR,其中有 15172 个被合并。在详述本次更新的内容之前,我们想强调,Flutter 的首要工作始终是高质量交付开发者们所需要功能。
Flutter 2.5 带来了一些重要的性能和工具改进,以帮助开发者们追踪应用中的性能问题。同时,加入了一些新的功能,包括对 Android 的全屏支持、 对 Material You (也称 v3) 的更多支持、对文本编辑的更新以支持切换键盘快捷键、在 Widget Inspector 中查看 widget 详情、在 Visual Studio Code 项目中添加依赖关系的新支持、从 IntelliJ / Android Studio 的测试运行中获得测试覆盖率信息的新支持,以及一个更贴近 Flutter 应用在真实的使用场景下的应用模板等。这个版本充满了令人兴奋的新更新,让我们开始介绍吧!
该版本进行了一些性能上的改进:首先是一项用于从离线训练运行中连接 Metal 着色器预编译的 PR (#25644[1]),这将最坏情况下的光栅化时间减少了 2/3 (如我们的基准测试所示),将第 99 百分位的帧时间减少了一半。我们在减少 iOS 卡顿方面取得了持续性的进展,这也是在这条道路上迈出的另一步。然而,着色器预热只是卡顿的一个来源。在该版本以前,处理来自网络、文件系统、插件或其他 isolate 的异步事件可能导致动画中断,这是另一个卡顿的来源。在该版本中我们对 UI Isolate 的事件循环的调度策略 (#25789[2]) 进行了改进,现在帧处理优先于其他异步事件的处理,在我们的测试中,其导致的卡顿已经被消除。
另一个原因是垃圾回收 (GC) 会暂停 UI 线程来回收内存。在该版本以前,一些图像的内存只能在 Dart VM 执行 GC 时以较慢的速度进行回收。在早期版本中,常用的做法是 Flutter 引擎会向 Dart VM 提示图像内存可以通过 GC 回收,理论上可以让内存回收更为及时。不幸的是,在实践中这造成了过多的回收,而且内存有时仍然不能被快速回收,导致无法避免在内存有限的设备上出现低内存的情况。在现在的版本中,未使用的图像的内存会尽可能快速地进行回收 (#26219[3]、#82883[4]、#84740[5]),这大大减少了 GC 的次数。
举个例子,在我们的一个测试中,播放了一个 20 秒的 GIF 动画,GC 的次数从需要 400 次下降到只需 4 次。更少的主要 GC,意味着更少的涉及图像出现和消失的动画卡顿,更少的 CPU 和电量消耗。
Flutter 2.5 的另一项性能改进是优化了 iOS 上 Dart 和 Objective-C/Swift、Android 上 Dart 和 Java/Kotlin 之间相互通信的延迟。作为 调整消息通道[6] 的一部分,我们从消息编解码器中移除了不必要的拷贝,在不同内容的大小和设备上减少了高达 50% 的延迟 (详见 #25988[7]、#26331[8])。
更多详情,请你参阅 Aaron Clarke 的文章:提高 Flutter 中的平台通道性能[9]。
如果你要构建 iOS 应用,我们还有最后一项性能更新:在该版本中,使用 Apple Silicon M1 Mac 构建的 Flutter 应用可以直接在 ARM 架构的 iOS 模拟器 (#pull/85642[10]) 上运行。这意味着无需使用 Rosetta 对 Intel x86_64 指令和 ARM 进行转换,这提升了 iOS 应用测试的性能,并规避了一些微妙的 Rosetta 问题 (#74970[11]、#79641[12])。这是 Flutter 在全面支持 Apple Silicon 的路程上迈出的又一步,敬请继续关注。
当然,没有 Dart 语言和它的运行时环境,就不会有现在的 Flutter,它建立在 Dart 语言和 runtime 之上。Flutter 2.5 同时带来了 Dart 2.14。新发布的 Dart 版本[13] 不仅带来了新的格式化使 级联[14] 操作更加清晰,还带来了支持忽略文件的新 pub 命令工具,以及新的语言功能 (包括传说中的无符号右移操作符的回归)。此外,这个版本带来了一套新的 Dart 和 Flutter 项目之间共享的标准代码规范提示,开箱即用,这也是 Dart 2.14 最精彩的部分。
flutter create
开箱即有一个 analysis_options.yaml 文件,预先使用了推荐的 Flutter lint。
当你创建一个新的 Dart 或 Flutter 项目时,你不仅可以使用这些规范,而且 只需要几个步骤[15] 就可以将这种相同的分析添加到你现有的应用中。关于这些规范的细节、新的语言功能和更多内容,请查阅:Dart[16] 2.14[17] 发布[18]。
Flutter 2.5 版本对框架进行了一些修复和改进。我们修复了关于 Android 全屏模式的一系列相关问题[19],该 Issue 获得了上百个点赞,全屏选项包括向后倾斜、沉浸模式、粘性沉浸模式和边到边四种。这一变化还增加了一种方法用来监听其他模式下的全屏变化。例如,如果用户在使用应用时,改变了系统界面的全屏模式,开发者现在可以通过代码让应用重新变为全屏,或执行其他操作。
在这个版本中,我们继续建立对新的 Material You (又称 v3) 规范的支持,包括对悬浮按钮尺寸和主题的更新 (#86441[20]),以及一个新的 MaterialState.scrolledUnder
状态,你可以通过 PR (#79999[21]) 中的示例代码看到它的效果。
当我们讨论滚动时,另一个改进是增加了额外的滚动指标通知 (#85221[22]、#85499[23]),即使用户没有滚动,也会提供可滚动区域的通知。例如,如下示例展示了滚动条根据 ListView 的实际大小而适时出现或消失的效果。
在这种情况下,你不需要写任何代码,就可以捕获 ScrollMetricNotification[24] 的变化。特别感谢社区贡献者 xu-baolin[25],他在这方面做了大量工作,并提出了一个很好的解决方案。
社区的另一杰出贡献是为 ScaffoldMessenger
增加了 Material 横幅的支持。在 Flutter 2.0[26] 中新增的 ScaffoldMessenger
,它提供了一种强大的方式,在屏幕底部显示 SnackBars 以向用户提供通知。在 Flutter 2.5 中,现在你可以在 Scaffold 顶部添加一个横幅,在用户将其关闭之前,它将一直保持在原位。
横幅的 Material 指南[27] 规定你的应用一次只能显示一个横幅,所以如果你的应用多次调用 showMaterialBanner
,ScaffoldMessenger
将持有一个队列,在前一个横幅被关闭时显示下一个新的横幅。感谢 Calamity210[28] 为 Flutter 的 Material 支持提供了有力补充。
在 Flutter 2.0 及其新文本编辑功能的基础上,我们在这个版本中添加了如文本选择器、拦截覆写任何键盘事件,以及覆写文本编辑的键盘快捷方式的能力 (#85381[29])。如果你想让 Ctrl - A 做一些自定义操作,而不是选择所有文本,你可以自行定义。DefaultTextEditingShortcuts[30] 类包含了 Flutter 在每个平台上支持的每个键盘快捷方式的列表。如果你想覆写其中的关联,请使用 Flutter 现有的 Shortcuts[31] widget,将任一快捷键重新映射到现有或自定义的意图,您可以将该 widget 放置在你想要覆写的地方。示例请参阅:API 文档[32]。
另一个得到大量改进的插件是 camera 插件[33]:
3795[34] [camera] android-rework 第 1 部分:支持 Android 相机功能的基础类 3796[35] [camera] android-rework 第 2 部分:Android 自动对焦功能 3797[36] [camera] android-rework 第 3 部分:Android 曝光相关功能 3798[37] [camera] android-rework 第 4 部分:Android 闪光灯和变焦功能 3799[38] [camera] android-rework 第 5 部分:Android FPS 范围、分辨率和传感器方向功能 4039[39] [camera] android-rework 第 6 部分:Android 曝光和对焦点功能 4052[40] [camera] android-rework 第 7 部分:Android 降噪功能 4054[41] [camera] android-rework 第 8 部分:最终实现的支持模块 4010[42] [camera] 在 iOS 上不触发平放时的设备方向 4158[43] [camera] 修复 iOS 上设置焦点和曝光点的坐标旋转 4197[44] [camera] 修复相机预览在设备方向改变时不总是重建的问题 3992[45] [camera] 防止在设置不支持的 FocusMode 时崩溃 4151[46] [camera] 引入 camera_web package
在 image_picker 插件[47] 上也做了很多工作,专注于端到端的相机体验。
3898[48] [image_picker] 图像采集器修复相机设备 3956[49] [image_picker] 在 Android 中将相机捕捉的存储位置改为内部缓存,以符合新的 Google Play 存储要求 4001[50] [image_picker] 删除了多余的相机权限请求 4019[51] [image_picker] 修复当相机作为源时的旋转问题
这些工作改善了 Android 的相机和 image_picker
插件的功能和健壮性。此外,你也许会注意到 camera 插件[52] 的 Web 功能已处于预览阶段 (#4151[53])。这个预览版提供了对查看相机预览、拍摄照片、使用闪光灯和变焦控制的基本支持,所有这些都可以在 Web 上进行。它目前不是一个 被认可的联合插件[54],因此在配置中,你需要明确这个插件仅能够在 Web 应用中 添加使用[55]。
最初的 Android 相机重构工作是由 acoutts[56] 贡献完成的。camera
和 image_picker
的工作是由 Baseflow[57] 完成的,这是一家专门从事 Flutter 的咨询公司,因其 在 pub.dev 上的 package [58] 而闻名。camera_web
的工作主要由 Very Good Ventures[59] 完成,这是一家位于美国的 Flutter 咨询公司。非常感谢你们对 Flutter 社区的贡献!
另一个有价值的社区贡献是由 fluttercommunity.dev 组织做出的,他们的代表作是 plus 系列插件[60]。随着新的 Flutter 版本发布,之前由 Flutter 官方团队维护的插件现在 “交接” 给了 fluttercommunity.dev 组织,在每个插件下方都会有下面类似的提示:
此外,由于这些插件不再积极维护,所以我们已取消了它们的 Flutter Favorite 标记。如果你还没有迁移到 plus 系列插件,我们建议你按照以下的表格进行对照迁移。
Flutter 2.5 对 Flutter DevTools 进行了大量的改进。首先是在 DevTools 中增加了对引擎更新的支持 (#26205[61]、#26233[62]、#26237[63]、#26970[64]、#27074[65]、#26617[66])。其中一组更新使 Flutter 能够更好地将跟踪事件与特定的帧联系起来,这有助于开发人员确定一个帧可能会超出预算的原因。你可以在 DevTools 框架图中看到这一点,该图表重构之后已经支持了实时展示;当你的应用正在渲染时,它们的数据会被填入该图中。从这个图表中选择一个构建帧,就可以跳转到该帧的时间线事件。
Flutter 引擎现在也能识别时间线中的着色器编译事件。Flutter DevTools 使用这些事件来帮助您诊断应用中的着色器编译缺陷。
有了这个新功能,DevTools 可以检测到你因着色器编译而丢失的构建帧,以帮助你修复这个问题。如果你希望像首次运行应用一样,使用 flutter run
命令并加上 --purge-persistent-cache
这个标记。这将清除着色器的缓存,以确保你重现用户在「首次运行」或「重新打开」 (iOS) 应用时看到的效果。此功能仍在开发中,所以请将您发现的 问题或改进建议[67] 提交给我们,以帮助发现和改进着色器编译工具。
此外,当你追踪应用中的 CPU 性能问题时,可能已经淹没在了来自 Dart 和 Flutter 库或引擎的原生代码的剖析数据中。如果你想关闭这些数据以专注自己的代码,那么你可以使用新的 CPU Profiler 功能 (#3236[68]),使你能够隐藏来自任何这些源的 Profiler 信息。
对于你没有过滤掉的类别,它们现在已经用颜色进行了分类 (#3310[69]、#3324[70]),这样你就可以很清晰地看到 CPU 火焰图内容对应的部分。
性能可能并不是你唯一想要调试的内容。新版本的 DevTools 带有对 Widget Inspector 的更新,当你将鼠标悬停在 widget 上时,可以评估对象、查看属性、widget 状态等等。
而且当你选择一个 widget 时,它会在新的 Widget Inspector Console 自动弹出,在那里你可以自由探索 widget 的属性。
除了新功能,Widget Inspector 也进行了改头换面。为了使 DevTools 成为理解和调试 Flutter 应用的最佳工具,我们与芬兰的创意技术机构 Codemate 合作[71],进行了一些更新。
如上图所示,你可以看到以下变化:
更好地传达调试切换按钮的作用 —— 这些按钮有新的图标、面向任务的标签,以及丰富的工具提示 (用于描述它们的功能和何时使用它们)。每个工具提示都进一步链接到了该功能的详细文档。 更容易查找和定位感兴趣的 widget —— Flutter 框架中经常使用的 widget 现在已在 Inspector 左侧的 widget 树视图中作为图标常驻。它们已经根据其类别使用颜色进行了分类。例如,布局 widget 显示为蓝色,内容 widget 显示为绿色。此外,每个文本 widget 现在会显示其内容预览。 更一致的 Layout Explorer 和 widget 树的颜色方案 —— 从 Layout Explorer 和 widget 树中识别出相同 widget 变得更容易了。例如,如上图所示中的「Column」widget 在 Layout Explorer 中是蓝色背景,在 widget 树视图中也有一个蓝色图标。
我们很乐意听到你对这些更新产生的任何 问题和改进建议[72] 以确保 DevTools 高效地运行。这些亮点仅是开始。关于 DevTools 在 Flutter 这个版本中的全部新内容,请查阅以下版本说明:
Flutter DevTools 2.3.2 版本说明[73] Flutter DevTools 2.4.0 版本说明[74] Flutter DevTools 2.6.0 版本说明[75]
IntelliJ / Android Studio 的 Flutter 插件在这个版本中也有一些改进,首先改进是运行集成测试的能力 (#5459[76])。集成测试是在设备上运行的整个应用测试,在 integration_test 目录下运行,并使用与 widget 单元测试相同的 testWidgets()
功能。
要在您的项目中添加集成测试,请 遵循 Flutter 文档网站上的说明[77]。要将测试与 IntelliJ 或 Android Studio 连接,请添加一个运行配置,启动集成测试,并连接一个设备供测试使用。运行配置可以让你在运行测试的同时,设置断点、步进等。
此外,Flutter 的最新 IntelliJ / Android Studio 系列插件允许您查看单元测试和集成测试运行的覆盖率信息。您可以通过「debug」按钮旁边的工具栏按钮来访问这个信息:
覆盖率信息将以红色和绿色的矩形显示在编辑窗口左侧的空隙中。在这个例子里,第 9 - 13 行被测试覆盖,但第 3 和 4 行没有被测试。
最新版本还包括预览来自 pub.dev 的 package 中使用的图标的新功能,这些 package 是围绕 TrueType 字体文件构建的 (#5504[78]、#5595[79]、#5677[80]、#5704[81]),正如 Material 和 Cupertino
图标支持预览一样。
要启用图标预览,你需要告诉该插件你正在使用哪些 package。在插件的设置 / 偏好页面有一个新的文本字段。
注意,这对定义为类中静态常量的图标有效,如屏幕截图中的示例代码所示。它不会对表达式起作用,例如 LineIcons.addressBook()
或 LineIcons.values['code']
。如果你是一个图标 package 的作者,而这个图标 package 并不适合这个功能,请 创建一个 Issue[82] 进行反馈。
更多有关 Flutter 的 IntelliJ / Android Studio 插件的更新信息,请参阅下列发布说明:
Flutter IntelliJ Plugin M57 发布[83] Flutter IntelliJ Plugin M58 发布[84] Flutter IntelliJ Plugin M59 发布[85] Flutter IntelliJ Plugin M60 发布[86]
Flutter 的 Visual Studio Code 插件在这个版本中也得到了改进,首先是两个新的命令「Dart: Add Dependency」和「Dart: Add Dev Dependency」 (#3306[87]、#3474[88])。
这些命令提供的功能与已经提供了一段时间的 Jeroen Meijer 的 Pubspec Assist 插件[89] 类似。这些新命令开箱即用,提供了一个从 pub.dev 定期获取的 package 的类型过滤列表。
你可能还对「Fix All」命令感兴趣 (#3445[90]、#3469[91]),该命令对 Dart 文件可用,可以在一个步骤中修复所有与 dart fix[92] 相同的问题。
你也可以在 VS Code 中,通过在 editor.codeActionsOnSave
中添加 source.fixAll
来设置为保存时运行。
又或者如果你想尝试一下预览功能,你可以启用 dart.previewVsCodeTestRunner
设置,看到 Dart 和 Flutter 测试通过新的 Visual Studio Code 测试运行器运行。
Visual Studio Code 测试运行器看起来与当前的 Dart 和 Flutter 测试运行器有些不同,它会在不同的会话中显示结果。Visual Studio Code 测试运行器还在编辑界面的左侧增加了新的间距图标 (Gutter icon),显示测试的执行结果状态,可以点击它来运行测试 (或右键点击上下文菜单)。
在之后的版本,现有的 Dart 和 Flutter 测试运行器将被移除,而采用新的 Visual Studio Code 测试运行器。
而这仅仅是 Visual Studio Code 插件新功能和修正的冰山一角。所有详情,请查阅下列发布说明:
v3.26[93] VS Code Test Runner 集成,Flutter 创建设置,... v3.25[94] 额外的依赖性管理改进,在文件 / 保存时修复所有,... v3.24[95] 依赖关系树的改进,更容易启动配置,编辑器的改进 v3.23[96] 配置文件模式的改进,改进依赖关系树,改进 LSP
在以前的 Flutter 版本中,你可能会被那些你不希望处理的异常所困扰,你可能希望它们触发调试器并找出它们的源头,但却发现 Flutter 框架没有让异常通过来触发调试器中的「未处理的异常」处理程序。在这个版本中,调试器现在可以正确地中断未处理的异常,而以前这些异常只是被框架捕获 (#17007[97])。这改善了调试的体验,调试器现在可以直接指向异常在代码中的抛出行,而不是指向框架深处的一个随机位置。与之相关的一个新功能是你能够决定 FutureBuilder 是否应该重新抛出或隐藏错误 (#84308[98])。这应该会给你提供更多的异常,以帮助你追踪 Flutter 应用中的问题。
自从 Flutter 诞生以来,就有了 Counter 应用模板,它有很多优点:它展示了 Dart 语言的很多特性,演示了几个关键的 Flutter 概念,而且它足够小,即使有很多解释性的注释,也能装进一个文件。然而,它并未对 Flutter 应用的实际使用场景提供一个特别好的展示。在这个版本中,你可以通过以下命令创建一个新的模板 (#83530[99])。
$ flutter create -t skeleton my_app
新的 Skeleton 模板,可生成包含两页的列表视图 Flutter 应用 (带详细视图),并遵循社区最佳实践。它的开发经过了大量的内部和外部评审,以提供一个更好的基础来构建一个达到产品级品质的应用。它支持以下功能:
使用 ChangeNotifier 来协调多个小工具 默认情况下,使用 arb 文件生成本地化。 包括一个示例图像,并为图像资源建立了 1x、2x 和 3x 文件夹。 使用「功能优先」的文件夹组织方式 支持 shared_preference 支持浅色和深色主题设计 支持多页之间的导航
随着时间的推移和 Flutter 最佳实践的发展,希望这个新模板也能随之发展。
如果你正在开发一个插件而不是一个应用,你可能会对 Pigeon 1.0 版本感兴趣。Pigeon 是一个代码生成工具,用于生成 Flutter 和其宿主平台之间类型安全的交互代码。你可以定义插件的 API 描述,并为 Dart 与 Java / Objective-C / Kotlin / Swift 生成模板代码。
Pigeon 已经应用在 Flutter 团队的一些插件中。这个版本提供了更多有用的错误信息,增加了对泛型、原始数据类型作为参数和返回类型以及多参数的支持,在未来它会被更广泛地使用。如果你想在自己的插件或 add-to-app 的项目中使用 Pigeon,请查阅 pigeon 插件页面[100] 找到更多信息。
以下是 Flutter 2.5 版本中的破坏性改动:
默认的设备拖动和滚动[101] v2.2 版后删除了废弃的 API[102] Package 介绍: flutter_lints[103] ThemeData 的 accent 属性已被弃用[104] 手势识别器清理[105] 将 AnimationSheetBuilder.display 替换为 collate[106] 使用 HTML 插槽在 Web 中渲染平台视图[107] 将 LogicalKeySet 迁移至 SingleActivator[108]
了解自 1.17 版本以来完整的破坏性改动列表,请参阅:Flutter 文档网站[109]。
随着我们继续更新 Flutter Fix (可在 IDE 中使用,也可通过 dart fix
命令使用),我们总共应用了 157 条规则,来迁移受破坏性改动以及任何弃用影响的代码。一如既往,我们非常感谢社区 提供的测试[110],帮助我们识别了这些破坏性改动。如需了解更多,请查阅: Flutter 破坏性改动政策[111]。
另外,随着 Flutter 2.5 的发布,我们将放弃对 iOS 8 的支持,正如 2020 年 9 月宣布[112] 的那样。放弃对市场份额不足 1% 的 iOS 8 的支持,使 Flutter 团队能够专注于使用范围更广的新平台。弃用意味着这些平台可能可以正常使用 Flutter,但我们不会在这些平台上测试新版本的 Flutter 或插件。您可以在 Flutter 文档网站[113] 上看到 目前 Flutter 支持的平台列表[114]。
最后,一如既往地感谢世界各地的 Flutter 社区组织和社区成员们,是社区让这一切成为可能。在本次更新中贡献和审核了 1000 多个 PR 的数百位开发者们,因为大家的努力才成就了本次的成果。让我们携手共同努力,为世界各地的开发者共同转变应用的开发流程,让更多开发者可以从一个代码库中交付更多应用,更快开发、部署到更多你所关心的平台。
敬请关注 Flutter 团队的更多更新,这一年还没有结束,请拭目以待!
感谢 flutter.cn 社区成员 (@AlexV525、@Vadaski、@MeandNi) 以及 Yuan 和 Lynn 对本文的审校和贡献。
文内链接
#25644: https://github.com/flutter/engine/pull/25644
[2]#25789: https://github.com/flutter/engine/pull/25789
[3]#26219: https://github.com/flutter/engine/pull/26219
[4]#82883: https://github.com/flutter/flutter/pull/82883
[5]#84740: https://github.com/flutter/flutter/pull/84740
[6]调整消息通道: https://files.flutter-io.cn/flutter-design-docs/2021_Platform_Channel%20Performance_Tuneup.pdf
[7]#25988: https://github.com/flutter/engine/pull/25988
[8]#26331: https://github.com/flutter/engine/pull/26331
[9]提高 Flutter 中的平台通道性能: https://medium.com/flutter/improving-platform-channel-performance-in-flutter-e5b4e5df04af
[10]#pull/85642: https://github.com/flutter/flutter/pull/85642
[11]#74970: https://github.com/flutter/flutter/issues/74970#issuecomment-858170914
[12]#79641: https://github.com/flutter/flutter/issues/79641
[13]新发布的 Dart 版本: https://medium.com/@mit.mit/announcing-dart-2-14-b48b9bb2fb67
[14]级联: https://dart.cn/guides/language/language-tour%23cascade-notation
[15]只需要几个步骤: https://flutter.cn/docs/release/breaking-changes/flutter-lints-package#migration-guide
[16]Dart: https://medium.com/dartlang/announcing-dart-2-14-b48b9bb2fb67
[17]2.14: https://medium.com/dartlang/announcing-dart-2-14-b48b9bb2fb67
[18]发布: https://medium.com/dartlang/announcing-dart-2-14-b48b9bb2fb67
[19]我们修复了关于 Android 全屏模式的一系列相关问题: https://github.com/flutter/flutter/pull/81303
[20]#86441: https://github.com/flutter/flutter/pull/86441
[21]#79999: https://github.com/flutter/flutter/pull/79999
[22]#85221: https://github.com/flutter/flutter/pull/85221
[23]#85499: https://github.com/flutter/flutter/pull/85499
[24]ScrollMetricNotification: https://master-api.flutter-io.cn/flutter/widgets/ScrollMetricsNotification-class.html
[25]xu-baolin: https://github.com/xu-baolin
[26]Flutter 2.0: https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65
[27]横幅的 Material 指南: https://material-io.cn/components/banners
[28]Calamity210: https://github.com/Calamity210
[29]#85381: https://github.com/flutter/flutter/pull/85381
[30]DefaultTextEditingShortcuts: https://github.com/flutter/flutter/blob/b524270af147847f64fa296cf6eed3633ffe683d/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart#L163
[31]Shortcuts: https://api.flutter-io.cn/flutter/widgets/Shortcuts-class.html
[32]API 文档: https://api.flutter-io.cn/flutter/widgets/DefaultTextEditingShortcuts-class.html
[33]camera 插件: https://pub.flutter-io.cn/packages/camera
[34]3795: https://github.com/flutter/plugins/pull/3795
[35]3796: https://github.com/flutter/plugins/pull/3796
[36]3797: https://github.com/flutter/plugins/pull/3797
[37]3798: https://github.com/flutter/plugins/pull/3798
[38]3799: https://github.com/flutter/plugins/pull/3799
[39]4039: https://github.com/flutter/plugins/pull/4039
[40]4052: https://github.com/flutter/plugins/pull/4052
[41]4054: https://github.com/flutter/plugins/pull/4054
[42]4010: https://github.com/flutter/plugins/pull/4010
[43]4158: https://github.com/flutter/plugins/pull/4158
[44]4197: https://github.com/flutter/plugins/pull/4197
[45]3992: https://github.com/flutter/plugins/pull/3992
[46]4151: https://github.com/flutter/plugins/pull/4151
[47]image_picker 插件: https://pub.flutter-io.cn/packages/image_picker
[48]3898: https://github.com/flutter/plugins/pull/3898
[49]3956: https://github.com/flutter/plugins/pull/3956
[50]4001: https://github.com/flutter/plugins/pull/4001
[51]4019: https://github.com/flutter/plugins/pull/4019
[52]camera 插件: https://pub.flutter-io.cn/packages/camera_web
[53]#4151: https://github.com/flutter/plugins/pull/4151
[54]被认可的联合插件: https://flutter.cn/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
[55]添加使用: https://pub.flutter-io.cn/packages/camera_web/install
[56]acoutts: https://github.com/acoutts
[57]Baseflow: https://www.baseflow.com/open-source/flutter
[58]在 pub.dev 上的 package: https://pub.flutter-io.cn/publishers/baseflow.com/packages
[59]Very Good Ventures: https://verygood.ventures/
[60]plus 系列插件: https://plus.fluttercommunity.dev/
[61]#26205: https://github.com/flutter/engine/pull/26205
[62]#26233: https://github.com/flutter/engine/pull/26233
[63]#26237: https://github.com/flutter/engine/pull/26237
[64]#26970: https://github.com/flutter/engine/pull/26970
[65]#27074: https://github.com/flutter/engine/pull/27074
[66]#26617: https://github.com/flutter/engine/pull/26617
[67]问题或改进建议: https://github.com/flutter/devtools/issues
[68]#3236: https://github.com/flutter/devtools/pull/3236
[69]#3310: https://github.com/flutter/devtools/pull/3310
[70]#3324: https://github.com/flutter/devtools/pull/3324
[71]Codemate 合作: https://codemate.com/
[72]问题和改进建议: https://github.com/flutter/devtools/issues
[73]Flutter DevTools 2.3.2 版本说明: https://groups.google.com/g/flutter-announce/c/LSNbc2rKIjQ/m/7Y7cWgO2CQAJ
[74]Flutter DevTools 2.4.0 版本说明: https://groups.google.com/g/flutter-announce/c/qenYe5LuHb8/m/tkWcBCVaAQAJ
[75]Flutter DevTools 2.6.0 版本说明: https://groups.google.com/g/flutter-announce/c/yBEZOWdV9nc/m/KCX3m2BpCAAJ
[76]#5459: https://github.com/flutter/flutter-intellij/pull/5459
[77]遵循 Flutter 文档网站上的说明: https://flutter.cn/docs/testing/integration-tests
[78]#5504: https://github.com/flutter/flutter-intellij/pull/5504
[79]#5595: https://github.com/flutter/flutter-intellij/pull/5595
[80]#5677: https://github.com/flutter/flutter-intellij/pull/5677
[81]#5704: https://github.com/flutter/flutter-intellij/pull/5704
[82]创建一个 Issue: https://github.com/flutter/flutter-intellij/issues
[83]Flutter IntelliJ Plugin M57 发布: https://groups.google.com/g/flutter-announce/c/nZPj0uIW3h4/m/2Xnx8KQtAwAJ
[84]Flutter IntelliJ Plugin M58 发布: https://groups.google.com/g/flutter-announce/c/WJUH0m6cu-U/m/_n0RltLFAAAJ
[85]Flutter IntelliJ Plugin M59 发布: https://groups.google.com/g/flutter-announce/c/CNzqxtybpBA/m/nSu7QabMAQAJ
[86]Flutter IntelliJ Plugin M60 发布: https://groups.google.com/g/flutter-announce/c/qc40yulxvAg/m/B_1HuGmoBQAJ
[87]#3306: https://github.com/Dart-Code/Dart-Code/issues/3306
[88]#3474: https://github.com/Dart-Code/Dart-Code/issues/3474
[89]Jeroen Meijer 的 Pubspec Assist 插件: https://marketplace.visualstudio.com/items?itemName=jeroen-meijer.pubspec-assist
[90]#3445: https://github.com/Dart-Code/Dart-Code/issues/3445
[91]#3469: https://github.com/Dart-Code/Dart-Code/issues/3469
[92]dart fix: https://dart.cn/tools/dart-fix
[93]v3.26: https://dartcode.org/releases/v3-26/
[94]v3.25: https://dartcode.org/releases/v3-25/
[95]v3.24: https://dartcode.org/releases/v3-24/
[96]v3.23: https://dartcode.org/releases/v3-23/
[97]#17007: https://github.com/flutter/flutter/issues/17007
[98]#84308: https://github.com/flutter/flutter/pull/84308
[99]#83530: https://github.com/flutter/flutter/pull/83530
[100]pigeon 插件页面: https://pub.flutter-io.cn/packages/pigeon
[101]默认的设备拖动和滚动: https://flutter.cn/docs/release/breaking-changes/default-scroll-behavior-drag
[102]v2.2 版后删除了废弃的 API: https://flutter.cn/docs/release/breaking-changes/2-2-deprecations
[103]Package 介绍: flutter_lints: https://flutter.cn/docs/release/breaking-changes/flutter-lints-package
[104]ThemeData 的 accent 属性已被弃用: https://flutter.cn/docs/release/breaking-changes/theme-data-accent-properties
[105]手势识别器清理: https://flutter.cn/docs/release/breaking-changes/gesture-recognizer-add-allowed-pointer
[106]将 AnimationSheetBuilder.display 替换为 collate: https://flutter.cn/docs/release/breaking-changes/animation-sheet-builder-display
[107]使用 HTML 插槽在 Web 中渲染平台视图: https://flutter.cn/docs/release/breaking-changes/platform-views-using-html-slots-web
[108]将 LogicalKeySet 迁移至 SingleActivator: https://github.com/flutter/flutter/pull/80756_yWRVR6Y
[109]Flutter 文档网站: https://flutter.cn/docs/release/breaking-changes
[110]提供的测试: https://github.com/flutter/tests/blob/master/README.md
[111]Flutter 破坏性改动政策: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[112]正如 2020 年 9 月宣布: https://flutter.cn/go/rfc-ios8-deprecation
[113]Flutter 文档网站: https://flutter.cn/docs/development/tools/sdk/release-notes/supported-platforms
[114]目前 Flutter 支持的平台列表: https://flutter.cn/docs/development/tools/sdk/release-notes/supported-platforms