Flutter 3.50 & Dart 3.14 发布,快来看看有什么更新吧

这次 Flutter 3.50 & Dart 3.14 感觉就像是在在把历史包袱扔掉,感觉还是一个挺不错的版本,别天天说我发 Flutter 问题了,今天打鸡血:

  • SDK 的 Material 与 Cupertino 正式废弃,彻底拆分成了独立包 material_ui 与 cupertino_ui
  • iOS 大量性能优化,比如触控响应优化直接快一整帧(60Hz 快 16ms,120Hz 快 8ms),Android release 禁止了外部 Intent 启动参数注入的高危漏洞, Hybrid Composition++ (HCPP) 优化
  • 全新 dart migrate ,FFIgen 与 JNIgen 原生直连正式 Stable

Material 和 Cupertino

在 Flutter 3.50 开始,SDK 内置的样式库就正式废弃了, package:flutter/material.dart 和 package:flutter/cupertino.dart 都需要改成 pub.dev 上的独立包 package:material_ui 和 package:cupertino_ui。

新的项目也默认走的 package:material_ui,老项目可以通过 dart fix --apply --code=migrate_design_widgets 自动迁移,执行后会:

  • 在 pubspec.yaml 添加独立的 material_ui / cupertino_ui 依赖
  • 把代码里所有的 package:flutter/material.dart 旧导包路径重写为新包路径
  • 自动同步更新本地化(Localizations)相关的代码和配置。

Framework

这个还真是史诗级更新,滚动视图(ScrollView / Slivers)一直是复杂业务 UI 的重灾区,这次 Flutter 3.50 针对呼声最高的几个痛点都处理合并了,比如裁剪、动态高度和响应式物理效果。

SliverClipRect 与 SliverClipRRect

以前当你在 CustomScrollView 里写了一个带圆角背景的 Sliver 区块的时候,或者顶上有个半透明的吸顶 SliverPersistentHeader(Pinned Header),当列表内容往上滚进吸顶 Header 下面时,普通的 ClipRRect 根本套不住 Sliver,因为它是 RenderBox 不是 RenderSliver,或者 UI 上会把吸顶重叠区弄错乱。

然后这次 PR #179003 在 rendering/sliver_clip.dart 中正式引入了 SliverClipRect 和 SliverClipRRect ,内置了 ClipOverlapBehavior 枚举,专门处理和其他 Sliver(尤其是吸顶 Header)发生重叠(SliverConstraints.overlap)时的裁剪行为:

arduino 复制代码
enum ClipOverlapBehavior {
  /// 忽略重叠区域。如果吸顶 Header 是半透明毛玻璃,下方内容可以透出来
  none,
​
  /// (默认)沿着重叠区域边缘截断裁剪矩形,确保内容绝不侵入吸顶 Header 底部
  followEdge,
​
  /// 保持形状向内收缩!当带有圆角的 Sliver 滚入吸顶 Header 下方时,
  /// 它不会把顶部圆角硬生生切平,而是让圆角贴着吸顶 Header 的下边缘平滑往下推!
  preserveShape,
}

而且在源码构造函数里,Flutter 也加上了 Dart 简洁的枚举点语法(.followEdge):

less 复制代码
SliverClipRRect(
  borderRadius: BorderRadius.circular(16),
  // 滚过吸顶 Header 时保留圆角形状,视觉极其精致
  clipOverlap: ClipOverlapBehavior.preserveShape,
  sliver: SliverList.builder(
    itemCount: 20,
    itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
  ),
)

除了裁剪,主干同期还合入了 SliverTransform (PR #192866),支持直接在 Sliver 层级做 2D/3D 矩阵变换,比如滚动视差、弹性拉伸、3D 翻折,可以通过双监听器(repaint 与 semanticsUpdate 分离)保证 120Hz 高刷动画下不会因为频繁刷新无障碍树而掉帧。

ListView.separated 支持 itemExtentBuilder

众所周知,当列表有上万条数据且每条高度固定的时候,传 itemExtent 性能会好很多,但是如果每条高度不固定,比如聊天记录、不同类型的卡片之类的,Flutter 之前给 ListView.builder 提供了 itemExtentBuilder, 可以按 index 按需算出每个 Item 的高度,避免为了测量高度去把屏幕外的 Widget 提前实例化出来。

但尴尬的是,平时最常用的带分割线列表 ListView.separated 居然一直不支持 itemExtentBuilder ,这次 PR #191157 终于补上了,现在 ListView.separated 也可以同时动态计算每个 Item 和每个 Separator(分割线)的尺寸:

perl 复制代码
ListView.separated(
  itemCount: 10000,
  // 偶数 index 为列表项,奇数 index 为分割线
  itemExtentBuilder: (int index, SliverLayoutDimensions dimensions) {
    if (index.isOdd) return 1.0; // 分割线高度 1px
    final itemIndex = index ~/ 2;
    return myItemHeightCache[itemIndex]; // 动态返回对应卡片高度
  },
  itemBuilder: (context, index) => MyCard(index: index),
  separatorBuilder: (context, index) => const Divider(height: 1),
)

ScrollPhysics.shouldUpdate

这次还有一个是动态切换物理属性不需要再重建列表的支持 ,以前如果你写了一个自定义 ScrollPhysics,比如根据用户手势状态改变阻尼系数,或者动态改变 allowImplicitScrolling,就算你在 setState 里传了带有新参数的同名 ScrollPhysics 实例,但是由于 runtimeType 没变,ScrollPosition 压根不知道物理属性变了,除非你暴力改 Key 重建整个滚动视图。

这次合并的 PR #189664 在 ScrollPhysics 基类里面新增了 @mustCallSuper bool shouldUpdate(covariant ScrollPhysics old) 方法,直接原生适配了优化能力:

scala 复制代码
class CustomDampingScrollPhysics extends ScrollPhysics {
  const CustomDampingScrollPhysics({required this.dampingFactor, super.parent});
  final double dampingFactor;
​
  @override
  bool shouldUpdate(covariant CustomDampingScrollPhysics old) {
    // 当自定义参数变化时返回 true,通知 ScrollPosition 立即响应新物理属性!
    if (dampingFactor != old.dampingFactor) {
      return true;
    }
    return super.shouldUpdate(old);
  }
}

其他

  • Scrollable.ensureVisible 不会再被吸顶 Header 挡住 :以前调用 ensureVisible 滚动到某个组件的时候,经常刚好滚到吸顶 Header 底下被盖住,现在它能把吸顶 Header 加入评估,让目标组件可以停在吸顶 Header 正下方的可视区
  • SliverFillRemaining 尾部偏移修正:正确计算尾随滚动偏移量的时候(Trailing scroll offset),不再出现莫名其妙的多余留白或越界
  • TreeSliver 与 NestedScrollView :TreeSliver 在展开/收起动画期间会自动裁剪根节点子项防止视觉穿透,NestedScrollView 修复了快速甩动(Fling)时偶发的越界位置跳变(这个之前是真恶心到了)
  • 桌面端滚动条鼠标手势收敛(RawScrollbar.mouseCursor) :以前鼠标悬停在滚动条附近区域光标就会变,现在严格限制在滑块(Thumb)和轨道(Track)本体上才触发悬停光标
  • TextInputType.numberWithOptions 添加了 password 选项
  • 新增的 Hyphens 枚举可以控制在换行时是否使用软连字符
  • 拖动即可以选择 PageView 中的文本
  • Android 可以用 AutofillHints.emailOTPCode 从电子邮件自动填充一次性验证码
  • DecorationImage 加了一个 placeholder ImageProvider ,容器背景就可以在加载时显示备用图像
  • FadeInImageTransition.fadeInOver 可以在平滑淡入淡出图像覆盖不透明占位符
  • 用 ResizeImage 上的 useLogicalSize 和 Image 上的 useLogicalCacheSize 可以将缓存的图像缩放到屏幕密度,不需要 BuildContext
  • 在 RawImage 上公开了 blendMode ,自定义控件就可以在绘制图像时直接应用颜色混合效果

路由

首先就是 showDialog 新增了 barrierBuilder,现在搞毛玻璃 Dialog 方便了不少,以前只有一个 barrierColor ,需要自己手搓一大坨 RawDialogRoute 或 PageRouteBuilder 。

less 复制代码
showDialog<void>(
  context: context,
  barrierBuilder: (context, animation, secondaryAnimation, child) {
    return FadeTransition(
      opacity: animation,
      child: BackdropFilter(
        filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
        child: child, // child 就是原本带点击关闭逻辑的默认遮罩层
      ),
    );
  },
  builder: (context) => const AlertDialog(title: Text('毛玻璃背景弹窗')),
);

其次就是 Navigator.popUntilWithResult ,以前 Navigator.popUntil 根本不支持传返回值 。这个 Issue #30112 从 2019 年一直到现在,之前只能用全局变量、EventBus 或者循环手动 pop 来绕开,现在终于新增了 Navigator.popUntilWithResult ,同时 pushNamed<T>() 也补齐了显式泛型返回值支持:

less 复制代码
// 1. 在 A 页面等待强类型结果:
final OrderResult? result = await Navigator.pushNamed<OrderResult>(
  context,
  '/checkout-step1',
);
​
// 2. 在 D 页面一键退回 A 页面,并把结果精准塞给刚才的 await!
Navigator.popUntilWithResult<OrderResult>(
  context,
  ModalRoute.withName('/cart'),
  OrderResult(orderId: 'ORD-202610', success: true),
);

最后是 Hero 动画与无障碍(WCAG):

  • 现在键盘弹出的时候 Hero 动画防抖 ,当嵌套的 Navigator 因为键盘弹出而改变尺寸的时候,Hero 组件现在会使用实时矩形坐标(Live rect coordinates),终于是解决了页面切换伴随键盘收起时 Hero 飞偏的视觉跳动
  • Escape按键会优先关闭 Tooltip(WCAG 1.4.13) :在桌面端场景,当屏幕上有打开的 Tooltip / RawTooltip 的时候,现在按 Esc 键会先关闭提示框并拦截本次按键向上冒泡
  • MediaQueryData.reduceMotion 和 SemanticsRole.slider :新增 MediaQuery.reduceMotionOf(context) 支持检测用户在系统设置里是否开启了"减弱动态效果",同时自定义滑块组件可通过 SemanticsRole.slider 准确通知屏幕阅读器
  • 焦点管理和 VoiceOver :WidgetsApp.router 内置了默认的 FocusScope,同时焦点排序支持 FocusOrder.lexical / .numeric 简写,修复了 Web 端和 iOS 端开启 VoiceOver 时元素滚入视口丢失焦点的问题

iOS 性能优化

这个版本等于 iOS 可以白捡了一次性能,因为在早期的 Flutter 架构里面,iOS 的触摸事件(touchesMoved)是在平台主线程(Platform Thread)派发的,但是驱动渲染的 CADisplayLink 跑在独立的 UI 线程上。

然后为了解决跨线程带来的事件抖动,之前引擎塞入了 PointerDataDispatcher、SmoothPointerDataDispatcher 和 touchRateCorrectionVSyncClient 等一堆缓冲调度层,代价就是触摸事件进来后往往要等到下一个 VSync 周期才能真正触发构建。

这个我们之前应该聊过。

现在线程合并后,其实 CADisplayLink 本来就一直跑在主线程上,而且现在的 UIKit RunLoop 比之前好多了,在事件派发阶段(Event Dispatch Phase)能严格保证一定发生在 CADisplayLink 回调阶段之前。

所以这次直接砍掉了所有历史遗留的异步缓冲器和 FlutterMetalLayer 里多余的 CADisplayLink,整条链路改造成了完全同步:

scss 复制代码
----- FRAME BOUNDARY (同一帧周期内) -----------------------------------------
[事件派发阶段]   touchesMoved 触发
   │ (完全同步,同一个 RunLoop Turn)
   ├──> Framework 处理指针事件并请求新的一帧 (Schedule Frame)
   └──> VSyncWaiter::AwaitVSync 注册等待
   │
[DisplayLink 阶段] (紧接着在同一周期内触发!)
   ├──> CADisplayLink 回调立即触发
   └──> Framework 立即生产当前帧并提交给 Raster 线程上屏!
----- FRAME BOUNDARY -------------------------------------------------------

最重要是什么?iOS 27 适配升级了,在新配对或新升级的 iPhone 上运行的时候,不会再出现白屏卡顿,同时Flutter CLI 现在会自动准备设备,并在准备失败时告诉用户该如何操作。

Flutter 3.50 还解决了在 iOS 27 设备上运行 flutter run 时出现的间歇性启动崩溃问题 ,特别是用 Xcode 27 构建,终于支持 iOS 17 以来首次在实体 iPhone 和 iPad 上恢复了 flutter screenshot 。

Android

Android 上我们应该也聊过,目前 3.50 开始,在 release 下会禁止 Intent Extras 启动,

  • 在 Release 构建,会直接忽略外部 Intent 传入的自定义路由(Routes)、入口函数(Entrypoints)、缓存引擎(Cached Engines)以及 --dart-flags 等引擎标志,正常的 Deep Links 深链跳转完全不受影响。
  • 在 Debug/Proile 模式下如果检测到被忽略的 Intent extras 会打印明确警告

然后就是以前提到过很多次的 HCPP ,这个 Android 原生视图(地图/WebView)的性能变得更好了,这次 Hybrid Composition++ (HCPP) 算是进化到完全体了,通过把原生 Android View 的合成工作直接移交给操作系统底层的 SurfaceControl / SurfaceFlinger,可以让 Flutter 图层与原生视图在系统合成器层面严丝合缝地对齐。

等于 HCPP 可以彻底消除了包含原生视图时的滚动画面撕裂(Scroll tearing)和软键盘文本输入抽风问题,甚至 HCPP 已经支持在原生 PlatformView 之上直接叠加毛玻璃背景模糊 (SurfaceFlinger blur regions,PR #194288),还有列表触底回弹时的原生视图同步拉伸变形(ui.ImageFilter.stretch,PR #191421),完美啊!!!

不过这个需要 Android 14+ 的 Impeller Vulkan 后端才行,还需要 flutter config --enable-hcpp

最后就是 AGP Built-in Kotlin,这个版本开始强制要求 Flutter 插件必须直接迁移到 AGP 内置的 Kotlin ,因为后面 Android 官方在 AGP 10 也会强制,同时是如果没有适配, pub.dev 也会对应扣减包质量评分(pub.dev score penalty)。

现在 Flutter 3.50 中,新建工程的 Android 模板会是:

  • Java 17(最低要求)
  • AGP 9.3.1 & Gradle 9.5.0
  • KGP 2.4.20
  • SDK 版本默认值 :compileSdkVersion/ targetSdkVersion 默认升到 API 36,minSdkVersion 默认升至 API 24

Impeller

Impeller 这个版本也是做了大量优化,虽然我经常发文吐槽,但是 Impeller 结局的问题还是很多的。

首先是 SDF(有符号距离场)渲染器扩军和文字阴影缓存

  • UberSDF 渲染加速(PR #188577 / PR #196056 / PR #195703) :Impeller 的 SDF(Signed Distance Field)渲染器现在不仅能画基础图形,还正式接管了直线(Lines)、细矩形(Thin rects)、细圆角矩形(Thin rounded rects)以及线性/径向渐变(Linear/Radial gradients) ,甚至把阴影渲染也统一到了 UberSDF Shader 下,也就是在 macOS 上,引擎甚至可以利用 SSBO(Shader Storage Buffer Objects) 大幅降低了 UberSDF 渐变的 GPU 开销
  • 首帧启动更快(Background IO Shader Setup) :在 OpenGL 后端下,Shader 的初始化与编译设置被移到了后台 IO Context 线程中并行完成,可以显著缩短了 App 冷启动的首帧上屏时间
  • 文字阴影按内容缓存(Text Shadows Cached by Content) :以前带阴影的文字在执行位移或者缩放动画的时候,每帧都在重新计算模糊阴影,现在文字阴影按文本内容缓存复用,动画帧率大幅提升
  • Flutter GPU 增强:新增 2D 纹理数组(2D texture arrays)支持,同时在 Pipeline 配置无效的时候会抛出更清晰的 Dart 层报错信息

其次是针对 Android GPU 优化,这个我们最近应该刚好聊过好几次,大概有:

  • Mali GPU 崩溃修复:在 OpenGL 缓冲区上传(Buffer uploads)前强制重新绑定纹理,彻底修复了部分 Mali GPU 机型上的底层驱动闪退。
  • PowerVR B 系列 GPU 自动拉黑 Vulkan:因为 B-series PowerVR GPU 的 Vulkan 驱动质量堪忧(笑死),引擎已将其加入 Vulkan 黑名单,自动安全回退到稳定的 OpenGL ES
  • OpenGL ES 2 兼容性扩大:后备存储(Backing stores)改用无尺寸纹理格式(Unsized texture format),拯救老旧低端设备
  • 透明动图解码修复:修复了 GIF/WebP 等动图在"第一帧完全不透明、后续帧带有 Alpha 透明通道"时解码画面错乱的 Bug

桌面端

这次 Flutter 桌面端在 3.50 中也加了了不少,比如:

平台 更新 解决问题
Windows 切换到 OpenGL ES 3 、修复离屏 MSAA 与高级滤镜死循环,直接翻转内容(Direct Flip) ,拉高文字 Gamma 对齐 Skia ,原生支持 UTF-8 文件路径 1. 少做一次全屏渲染拷贝,GPU 占用显著下降; 2. 以前 Windows 上新管线文字发虚发细,现在调高 Gamma 后文字像以前 Skia 一样清晰饱满; 3. Windows 用户名或安装目录带中文/日文/Emoji 时,再也不会因为路径编码问题打不开文件了!
macOS 窗口内容自适应尺寸(Content-sized / shrinkWrap) ,首帧就绪后再显示窗口(Deferred show) 以前做 macOS 弹窗、工具小浮窗,很难让原生窗口大小自动跟着里面 Flutter Widget 的高度走,而且新开窗口瞬间会闪一下白屏。现在不仅能自动包裹内容大小,还能等第一帧画好再把窗口亮出来,丝滑无闪烁!
Linux 修复离屏 MSAA 抗锯齿 ,WindowControllerLinux 开放无边框、透明与原生拖拽 API(PR #192356) Linux 下矢量图形边缘不再有锯齿,并且不用装第三方插件就能自己画标题栏、做透明异形窗口了!!!!
跨平台多窗口 WindowManager 移出 WidgetsApp 副窗口(Secondary windows)现在可以挂载完全独立的 Widget 子树,不再强行和主窗口绑在同一棵 WidgetsApp 树下。

特别是 Linux 端的 PR #192356,在 WindowControllerLinux 现在支持直接暴露底层能力:

  • setDecorated(false):关掉 GTK 默认画的系统标题栏和边框
  • setAppPaintable(true) 和 setBackgroundColor(...):阻止 GTK 用系统主题背景色填充窗口,让 Flutter 没画东西的地方实现真正的全透明镂空
  • beginMoveDrag() 和 beginResizeDrag(WindowDragEdge):把鼠标按下事件直接交接给 Linux 窗口管理器(Window Manager),让你用自定义 Flutter Widget 轻松实现窗口拖拽移动和八方向边缘缩放

最后, RegularWindow 现在更名为 Window ,shrinkWrap 属性也取代了 sizedToContent 和 Flutter 布局命名方式保持一致,同时 WindowManager 处于 WidgetsApp 上位, 这样辅助窗口就可以运行自己独立的用户界面和导航状态。

Web

首先是 Safari 和 Firefox 现在都开启;额 WebAssembly (Wasm),可以做到帧率翻倍,目前 Safari 26.2+(macOS & iOS)和 Firefox 147+ 也可以跑 Flutter Wasm 了:

在重度 Widget 压测基准下,Safari 和 Firefox 运行 Wasm 的帧率是传统 JavaScript 编译模式的 2 倍以上

目前你可以在项目的 flutter_bootstrap.js 配置里面,把 webkit(Safari)和 gecko(Firefox)加进 wasmAllowList 白名单,然后用 flutter build web --wasm 构建的时候,工具会同时产出 Wasm 和 JS,遇到老旧浏览器会自动无缝回退到 JS 模式。

另外就是旧版 Web 库正式废弃 ,为了全面拥抱 Wasm,历史悠久的 dart:html、dart:js、dart:js_util 和 package:js 已被正式标记为废弃(Deprecated)并将被移除 ,所有 Web 互操作必须用 dart:js_interop 和 package:web。

然后就是最实用的内置静态资源内容哈希 :--web-content-hash,现在可以在构建的时候自动补全:

  • 自动全量哈希 :对 JS/Wasm 入口文件、Source Maps(PR #193614)和 build/web/assets/** 下的所有静态资源计算内容哈希并重命名,自动把哈希映射关系注入 flutter_bootstrap.js 和资源清单
  • 现在可以在 CDN / Nginx 上对所有带哈希的文件设置 Cache-Control: public, max-age=31536000, immutable(永久强缓存),同时只需要对 index.html 和 flutter_bootstrap.js 设置 no-cache 即可
  • 自动生成 Service Worker 清单 :自动在 build/web/precache_manifest.json 生成预缓存清单(PR #192953),方便你对接自定义 Service Worker 或 Workbox 离线管线

最后是浏览器原生文字排版 WebParagraph 可以做到 CanvasKit 减少 31% 的体积 ,为什么以前 Flutter Web 首次加载那么慢?大多都是因为 CanvasKit 渲染器为了在 Canvas 上自己排版文字,不得不把一整套 C++ 字体解析与排版引擎(HarfBuzz / FreeType / ICU 数据表)打包进 WebAssembly,光 canvaskit.wasm 就要 5.46 MB,如果而且遇到生僻中文、多国语言或者新 Emoji 的时候,还得临时发网络请求去下载 Fallback 字体,没加载出来之前满屏都是"豆腐块(□)"。

php 复制代码
{{flutter_js}}
{{flutter_build_config}}
_flutter.loader.load({
  config: {
    wasmAllowList: {
      blink: true,
      webkit: true,
      gecko: true,
    },
  },
});
​

Flutter 团队和 Chrome 团队深度合作之后,基于浏览器的 Enhanced TextMetrics API 打造了全新的 WebParagraph,牛逼有木有:

  • 直接让浏览器替 Canvas 排版系统字体:把文字塑形(Font shaping)和测量工作交给浏览器原生能力,然后再绘制到 Canvas 上
  • CanvasKit 体积暴减 ~31% :砍掉内置的 C++ 字体解析器后,CanvasKit 下载体积直接从 ~5.46 MB 缩减到 ~3.75 MB
  • 零"豆腐块"、原生彩色 Emoji:直接调用操作系统本地字库,不需要再发起额外的 Fallback 字体网络请求,生僻多语言字符和系统原生彩色 Emoji 直接渲染

原生互操作 Stable

现在全新同步的 FFI 同步原生调用正式 Stable 了:

基本是 Native 三剑客全面就位:

  • FFIgen(正式 Stable) :自动扫描 Apple 平台头文件,生成调用 Objective-C 和 C API 的 Dart 绑定代码,比如 iOS 新系统特性发布可以第一天就能直接调,不用等第三方插件更新
  • JNIgen(正式 Stable) :自动扫描 Android / Java / Kotlin 类,生成直接调用 Android 原生 API 的 Dart 绑定代码
  • Pigeon(强烈推荐在生产环境使用) :Pigeon 现在底层已经全面改用 FFIgen 和 JNIgen 来生成绑定,官方核心插件 shared_preferences 已经率先完成了迁移验证

Dart 3.14 与工具链

首先是全新命令:dart migrate ,能自动帮你处理 Breaking Changes ,可以会自动帮升级 pubspec.yaml 中的 SDK 版本约束,自动修复破坏性 API 变更,同时将旧语法迁移现代化。

bash 复制代码
# 先预览一下升级会改动哪些地方,不实际修改文件
dart migrate --dry-run
​
# 确认无误后执行一键迁移
dart migrate

其次是 dart pub get 与 Dart Analysis Server 全面提速,如果你遇到过在大型多包项目(Monorepo)里,或者用了 Freezed / Riverpod 等分析器插件之后,IDE 经常转圈圈,按保存自动格式化(Format on Save)要卡好几秒才动,那这个就很实用了。

Dart 3.14 对日常工具链做了深度手术:

  • dart pub get 会在包元数据没有任何变化时,直接跳过重复网络下载

  • Find References(查找引用)和启动提速 ,可以大幅加快了文件发现速度,尤其是在包含大量 Analysis Contexts 的多包 Monorepo 工作区里面,修改 package_config.json 或者 analysis_options.yaml 后的分析器重启速度也显著提升

  • Analyzer Plugins 作用域也开始精准收敛,会将分析器插件的分析根目录严格限制在插件实际生效的 Context 根目录下,避免插件去全盘扫描无关包,插件运行速度暴涨

  • 写代码、格式化优化:

    • 以前后台分析任务经常阻塞代码格式化(Formatting)等前台操作,现在后台任务大幅降低了阻塞优先级
    • 大幅优化了 documentColor 请求 (就是 IDE 代码行号旁边显示 Color(0xFF...) 颜色预览小方块的那个 LSP 请求),以前编辑文件时这个请求经常把分析队列堵死,现在它能做到瞬间完成

还有我们之前说的,开发者现在可以将 Agent Skills 直接放在 pub.dev 软件包的顶层 skills/ 目录,这样应用程序开发人员就可以使用 dart run skills@ get 从软件包依赖项中发现并安装技能。

发布之前,作者可以在 CI 中运行 package:skills_lint 来检查 SKILL.md frontmatter、目录结构等,以及与 Agent Skills 规范相符的命名约定。

最后就是 DartPad 也优化了, preview.dartpad.dev 又又又重构了:

  • 增加了零远程服务器等待(Local WebAssembly Toolchain),以前的 DartPad 是把你写的代码发给 Google 远端服务器编译分析再把结果传回来,网络一卡甚至连代码补全都没有,现在的 DartPad 直接把 Dart 编译器(Compiler)、代码分析器(Analyzer)甚至 pub 客户端全部编译成了 WebAssembly,直接跑在你浏览器本地的 Web Worker 线程
  • 支持导入 pub.dev 上的任意包 ,只要是支持 Web 的 pub.dev 第三方包,就可以都能直接在浏览器里实时拉取试用
  • 支持多文件工程(Multi-file support) ,不需要把所有代码塞进一个 main.dart

弃用

因为 CocoaPods 即将只读,所以需要用户抓紧迁移到 Swift Package Manager (SPM):

  • Deadline 是 2026 年 12 月,到时候 CocoaPods Trunk 将正式停止接受任何更新,变为只读状态
  • 在 Flutter 3.50 中,如果你的项目还没有开启 Swift Package Manager(或者手动禁用了它),CLI 构建时会直接弹出警告

其次 Intel Mac 停止支持,Flutter 官方已经停止在 Intel 芯片的 Mac 上运行 CI 测试,而且当你用 Intel Mac 编译 Flutter 3.50 项目的时候,CLI 会弹出一次性警告,未来的版本将彻底移除对 Intel Mac 的支持。

最后

我感觉 Flutter 3.50 是近期最值得更新的版本了,虽然肯定还有坑,但是至少是一个带来巨大提升的版本。

相关推荐
非优秀程序员8 小时前
第10章 千团出世|《互联网产品恩仇录》
前端
非优秀程序员8 小时前
第11章 小高在对面|《互联网产品恩仇录》
前端
非优秀程序员8 小时前
第14章 只剩美团|《互联网产品恩仇录》
前端
非优秀程序员8 小时前
第09章 老乡何必为难老乡|《互联网产品恩仇录》
前端
非优秀程序员8 小时前
第03章 三大门户,烽烟起于瀛海威|《互联网产品恩仇录》
前端
曦樂~12 小时前
【Web Development】02 CSS
前端·css
风骏时光牛马12 小时前
后端服务接口开发与数据逻辑处理
前端
东鹏特饮12 小时前
经典打砖块(Breakout)游戏
前端·css·css3