Flutter 2.8 发布 | 性能及工具链优化、Firebase 功能、WebView 3.0

官方发布说明:medium.com/flutter/wha…

北半球的冬意已至,黄叶与气温均随风而落,而年终的最后一个稳定版本已悄然来到你的面前。 让我们向 Flutter 2.8 打声招呼~ 本次更新包含了 207 位贡献者和 178 位审核者 的辛勤劳作, 所有人共同产出了 2424 个 PR,关闭了 2976 个 issue。 在此特别感谢本次发布中最突出的社区贡献者:来自 Very Good Ventures 的 Flutter 开发工程师 Bartosz Selwesiuk, 他专注于 Web 平台的 camera 插件并提交了 23 个 PR。

以上的所有产出让 Flutter engine 和 DevTools 都有了非常显著的性能提升, 同时带来的还有 Google 移动端广告 SDK Flutter 版本的稳定版发布、 一系列针对 Firebase 的新功能和优化、Flutter WebView 3.0、 新的 Flutter Favorite package、向桌面端 Stable 迈出的一大步, 以及支持更多 package 的新版本 DartPad。 虽然这是今年最后一个稳定版本,但它并不是最不重要的。让我们一起来看看!

性能

Flutter 的首要目标是一如既往地保证其质量。 我们花费了大量时间以确保 Flutter 在多种多样的设备上都能流畅且稳定地运行。

应用启动

本次更新优化了应用启动的延迟。 我们在拥有一百万行以上的代码量的 GPay 应用上进行了测试,以确保改动在实际生产的应用上有效。 这些改动将 GPay 在低端 Android 设备上启动的时间减少了约 50%,高端设备上减少了约 10%

我们对 Flutter 调用 Dart VM 的 GC 策略也做了一些改进,以此避免在程序启动期间出现不合时宜的 GC。 例如,在 Android 设备上渲染出第一帧前,Flutter 仅在 TRIM_LEVEL_RUNNING_CRITYCAL 及高于其等级的信号出现时,通知 Dart VM 有内存压力 。 在本地测试中,低端 Android 设备的初始帧出现间隔时间最多减少了约 300ms

在先前的 Flutter 版本中, 出于谨慎考虑 , 在创建 PlatformView 时会阻塞平台线程。 在经过仔细的推理和测试后 , 我们删除了部分序列化的步骤,使得 GPay 在低端设备上的启动时间至少减少了 100ms

长久以来,在初始化首个 Dart isolate 前初始化默认的字体管理器会引入人为的延迟。 由于它是首要的延迟瓶颈,所以 将默认字体管理器的初始化延迟 到与首个 Dart isolate 同时运行,降低了启动的延迟,并让上述的所有启动优化的表现更加明显。

应用内存

由于 Flutter 会尽可能快地加载 Dart VM 的服务 isolate, 并将其和绑定在应用内的 AOT 代码一并加载到内存中, 这会导致 Flutter 开发人员在部分内存 有限制的设备上难以追踪内存指标 。 在 Flutter 2.8 版本中,Android 设备上 Dart VM 的服务 isolate 已被拆分至单独的 bundle 中 , 可以单独加载,减少了在其加载前约 40MB 的内存使用。 原本 Dart VM 向操作系统发送 AOT 程序的内存用量的通知, 已转由一个无需多次读取的文件支持,后续的内存占用量进一步减少了约 10%。 因此,先前保存了文件数据拷贝的内存可以回收并用于其他用途。

性能分析

某些场景下,开发者希望能同时看到 Flutter 和 Android 的性能追踪事件, 又或者是在生产模式下查看追踪事件来更好地了解应用的性能问题。 为了这一需求,Flutter 2.8 现在可以选择在应用启动后, 将性能追踪事件发送至 Android 的事件记录器,在生产模式下也同样如此。

Flutter 性能追踪事件现在显示在 Android systrace 记录工具中(底部)

此外,一些开发人员想要更多的关于光栅缓存行为的性能跟踪信息, 以减少制作动画效果时的卡顿,这允许 Flutter 快速地对昂贵的、重复使用的图片进行复用而不是重新绘制。 性能跟踪中的新的 流事件让开发人员可以跟踪光栅缓存图片的生命周期。

Flutter DevTools

对于调试性能问题,新版的 DevTools 添加了一个新的「增强跟踪」功能, 用来帮助开发者诊断消耗较大的构建、布局和绘制操作引起的 UI 卡顿。

启用任何一个追踪功能后,时间轴中将视情况展示 Widget 的构建、RenderObject 布局和 RenderObject 绘制的事件。

此外,新版的 DevTools 增加了应用程序启动性能的分析支持。 该配置文件包含从 Dart VM 初始化到第一个 Flutter 帧渲染的 CPU 样本。 在你按下「Profile app start up」按钮并加载应用程序启动配置文件后, 你将看到为配置文件选择了「AppStartUp」用户标签。 你还可以通过在可用用户标签列表中选择此用户标签过滤器(如果存在)来加载应用程序启动配置文件。 选择此标签会显示你的应用程序启动的个人资料数据。

Web 平台的平台视图 (PlatformView)

不仅仅是 Android 和 iOS 平台获得了性能提升,本次发布同时包含了对 Flutter Web 平台视图的性能优化。 平台视图是从宿主平台向 Flutter 嵌入 UI 组件的媒介。 Flutter Web 使用 HtmlElementView widget 实现了这一功能,让你能在 Flutter Web 应用中嵌入 HTML 元素。 如果你正在使用 google_maps_flutter 插件或 video_player 插件的网络版本, 或者你正在遵循 Flutter 团队关于 如何优化网络上显示图像 的建议,那么你正在使用平台视图。

在之前版本的 Flutter 中,嵌入平台视图会创建一个新的 canvas,每嵌入一个平台视图都会新增一个 canvas。 创建额外的 canvas 是十分消耗性能的操作,因为每个 canvas 的大小都与整个窗口相等。 在 Flutter 2.8 中,将 复用为先前的平台视图创建的 canvas , 因此,你不会在应用程序的整个生命周期内产生每秒 60 倍的成本,而是只有一次创建的成本。 这意味着你可以在 Web 应用程序中拥有多个 HtmlElementView 实例而不会降低性能, 同时还可以减少使用平台视图时的滚动卡顿。

生态

Flutter 不仅仅是框架、引擎和工具——pub.dev 上现有超过 2w 个与 Flutter 兼容的包和插件,而且每天都在增加。 Flutter 开发人员大量的日常操作也是庞大的生态系统的一部分, 所以让我们来看看自上一个版本以来 Flutter 生态系统中有什么改变。

适用于 Flutter 广告的 Google 广告

首先也是最重要的是, Google Mobile SDK for Flutter 已于 11 月正式发布 。 此版本支持 5 种广告格式,集成了 AdMob 和 Ad Manager 支持, 并包含一个新的中转功能的测试版,可以帮助你优化广告展现的效果。 有关将 Google Ads 集成到 Flutter 应用程序以及其他货币化选项的更多信息, 请查看 flutter.dev 上的页面

WebView 3.0

这次 Flutter 附带的另一个新版本是 webview_flutter 插件 的 3.0 版本。 因为新功能的数量增加,我们提升了主要版本号,但也因为 Web 视图在 Android 上的工作方式可能发生了重大变化。 在之前的 webview_flutter 版本中,Hybrid composition 已经可用,但不是默认的。 而现在它修复了先前默认以虚拟显示模式运行的许多问题。 根据用户反馈和我们的问题跟踪,我们认为是时候让 Hybrid composition 成为默认设置了。 此外,webview_flutter 还增加了一些呼声极高的功能:

  • 支持使用 POST 和 GET 来加载内容
  • 加载文件或字符串内容为 HTML
  • 支持透明背景
  • 在加载内容前设置 Cookies

此外,在 3.0 版本中,webview_flutter 为新平台提供了初步支持:Flutter Web。 已经有很多人要求能够在 Flutter Web 应用程序中托管 Web 视图, 这允许开发者利用单个源代码库构建移动或 Web 应用程序。 在 Flutter Web 应用程序中托管 Web 视图是什么样的? 从编写代码的角度来看,其实是一样的:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';

void main() {
  runApp(const MaterialApp(home: HomePage()));
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();

    // required while web support is in preview
    if (kIsWeb) WebView.platform = WebWebViewPlatform();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('Flutter WebView example')),
    body: const WebView(initialUrl: 'https://flutter.dev'),
  ;
}

在 Flutter Web 上运行时,它会按你的预期工作:

请注意,当前 webview_flutter 的 web 实现有许多限制,因为它是使用 iframe 构建的, iframe 仅支持简单的 URL 加载,无法控制加载的内容或与加载的内容交互。 但是,由于需求呼声太高,我们决定将 webview_flutter_web 作为未经认可的插件提供。 如果你想尝试一下,请将以下内容添加到你的 pubspec.yaml 中:

dependencies:
  webview_flutter: ^3.0.0
  webview_flutter_web: ^0.1.0 # 显式依赖未经认可的插件

如果你对 webview_flutter v3.0 有任何反馈,无论是否是关于 Web 平台, 请将问题记录在 Flutter 仓库中 。 此外,如果你之前没有使用过 webview 或者你想复习一下, 请查看新的 webview codelab , 它将带你逐步完成在 Flutter 应用程序中托管 web 内容的过程。

Flutter Favorites

Flutter 生态系统委员会再次召开会议,将以下 package 指定为 Flutter Favorite 的 package:

使用 flex_color_scheme 构建的可灵活折叠的应用

祝贺这些 package 的作者,并感谢你通过你的辛勤工作支持 Flutter 社区。 如果你有兴趣提名你最喜欢的 Flutter 包加入 Flutter Favorite 嘉奖, 请按照 Flutter Favorite 计划页面 上的指南和说明进行操作。

特定平台的插件 (plugin package)

如果你是插件作者,你必须决定你将支持哪些平台。 如果你正在使用特定于平台的原生代码构建插件, 你可以 使用项目 pubspec.yaml 中的 pluginClass 属性 来实现,该属性将指定提供原生功能的原生类名:

flutter:
  plugin:
    platforms:
      android:
        package: com.example.hello
        pluginClass: HelloPlugin
      ios:
        pluginClass: HelloPlugin

然而,随着 Dart FFI 变得更加成熟,有可能使用 100% 的 Dart 实现特定平台的功能, 就像 path_provider_windows package 所做的那样。在这种情况下,你没有任何本地类可以使用, 但你仍然希望将你的包指定为仅支持某些平台。 此时你可以改用 dartPluginClass 属性:

flutter:
  plugin:
    implements: hello
    platforms:
      windows:
        dartPluginClass: HelloPluginWindows

经过这样的设置后,即使你没有任何本机代码,也可以为特定平台定制插件。 你还必须提供 Dart 插件的类, 有关详细内容,你可以在 flutter.dev 上的仅 Dart 平台实现文档 中进行扩展阅读。

桌面平台

Flutter 2.8 版本在 Windows、macOS 和 Linux 稳定版本的道路上又迈出了一大步。 我们的目标质量标准很高,包括国际化和本地化支持, 例如 新的中文输入法支持韩语输入法支持 以及刚刚合并的 Kanji(日文)输入法 支持。 或者,就像我们在紧密构建 Windows 辅助功能的支持 一样。 对于 Flutter 来说,在 Stable 渠道的 desktop 上运行是不够的, 它必须在世界各地的语言和文化以及不同能力的设备上运行良好。 我们还没有达到我们想要的目标,但未来可期!

其中一个例子是我们重构了 Flutter 处理键盘事件以允许同步响应的架构。 这使 widget 能够处理按键并拦截它在整个 widget tree 中的其余部分中的传递。 我们在 Flutter 2.5 中完成了这项工作的落地,并在 Flutter 2.8 中修复了许多问题。 这是对我们如何处理特定于设备的键盘输入的方式的重新设计, 和重构 Flutter 处理文本编辑方式的持续工作的补充, 所有这些都是用键盘这样输入密集型的桌面应用程序所必需的。

此外,我们还在继续 向 Flutter 扩展视觉密度的定义 , 暴露对话框对齐方式的设置,以便开发者可以实现更加友好的桌面 UI。

最后,Flutter 团队并不是唯一一个在为了 Flutter desktop 付出心血的团队。 举个例子,Canonical 的桌面团队正在与 Invertase 合作, 在 Linux 和 Windows 上开发最流行的 Flutter Firebase 插件。

你可以在 Invertase 博客上 阅读有关预览版的更多信息。

DartPad

如果没有工具的改进,那么这个 Flutter 新版本的发布是不完整的。 我们将重点介绍 DartPad 的改进,其中最大的改进是对更多软件包的支持。 事实上,目前共有 23 个 package 可供导入使用。除了几个 Firebase 服务之外,该列表还包括诸如 bloc、characters、collection、google_fonts 和 flutter_riverpod 等流行的 package。 DartPad 团队会继续添加新的 package,如果你想查看当前支持哪些软件包,可以单击右下角的信息图标。

如果你想了解随着时间的推移向 DartPad 添加新包的计划, 请查看 Dart wiki 上的这篇文章 。 还有另一个新的 DartPad 功能也非常方便。 在此之前,DartPad 总是以运行最新的 stable 版本运行。 在新版本中,你可以使用状态栏中新的 渠道菜单 来切换最新的 Beta 渠道版本以及之前的 stable 版本(称为“旧渠道”)。

如果你正在撰写一篇博客文章,而最新的稳定版本还不够新,这将非常有用。 (其实方便了切换不同的渠道进行调试和 BUG 验证。)

移除 Dev 渠道

Flutter「渠道」决定了 Flutter 框架和引擎在你的开发机器上变化的速度, stable 代表最少的变更,而 master 代表最多。 受到团队资源的限制,我们最近将停止更新 dev 渠道。 虽然我们确实收到了一些相关的问题,但我们发现只有不到 3% 的 Flutter 开发人员使用 dev 渠道。 因此,我们决定启动正式停用 dev 渠道的进程。 虽然很少有开发人员使用 dev 渠道,但 Flutter 工程师需要花费大量时间和精力来维护它。 如果你将所有时间都花在 stable 渠道上(正如超过 90% 的 Flutter 开发人员所做的那样), 那么这项改动将不会影响你的日常开发。 通过放弃它,你可以少做一个决定,而 Flutter 团队可以将时间和精力花在其他事情上。 你可以使用 flutter channel 命令来决定你想要哪个渠道。 以下是 Flutter 团队对每个渠道的看法:

  • Stable 渠道 代表我们拥有的最高质量的构建。它们每季度(大致)发布一次,并针对中间的关键问题进行热修复。 这是「慢」通道:安全、成熟、长期服务。
  • Beta 渠道 为那些习惯于更快节奏的开发者提供了一种快速调整的替代方案。 目前每月发布,发布前稳定。这是「快速」通道。如果 dev 渠道正在满足 beta 渠道无法满足的需求, 我们可能会改变我们对 beta 渠道的看法来满足这些需求 (例如,加速发布 beta 的节奏或降低我们对 beta 执行的测试和热修复级别)。
  • Master 渠道 是我们活跃的开发渠道。我们不提供对该渠道的支持,但我们针对它运行了一套全面的单元测试。 对于对不稳定的构建感到满意的贡献者或高级开发者而言,这是适合他们的渠道。 在这个频道上,我们跑得很快,打破了一些东西(然后会很快地修复它们)。

当我们在未来几个月停用 dev 渠道时,请考虑使用 beta 或 master 渠道, 这取决于你对变更的容忍度以及你对最新和最好的 SDK 的平衡点。

破坏性更改

与往常一样,我们努力减少每个版本中破坏性更改的数量。 在此版本中,Flutter 2.8 除了已过期并根据我们的 重大变更政策 被删除的已弃用 API 之外,没有重大变更。

  • 90292 Remove autovalidate deprecations
  • 90293 Remove FloatingHeaderSnapConfiguration.vsync deprecation
  • 90294 Remove AndroidViewController.id deprecation
  • 90295 Remove BottomNavigationBarItem.title deprecation
  • 90296 Remove deprecated text input formatting classes

如果你仍在使用这些 API 并想了解如何迁移代码,你可以阅读 flutter.dev 上的迁移指南 。 与往常一样,非常感谢社区 贡献了测试用例 , 帮助我们识别这些重大更改。

总结

在我们结束 2021 年并展望 2022 年之际,Flutter 团队要对整个 Flutter 社区的工作和支持表示感谢。 诚然,我们正在为世界上越来越多的开发人员构建 Flutter, 但如果没有你和每位开发者的存在,我们也无法维护并构建它。 Flutter 社区与众不同,我们感谢你所做的一切。 祝你假期愉快,我们新的一年见!