🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

Flutter 3.38 發布,快來看看有什麼更新吧

在 11 月 13 日的 FlutterFlightPlans 直播中,Flutter 3.38 如期而至,本次版本主要涉及 Dot shorthands、Web 支援增強、性能改進、問題修復和控件預覽等方面

Flutter 3.38

Dot shorthands

在 Dart 3.10 + Flutter 3.38 中開始默認支持 Dot shorthands,通過 Dot shorthands 可以使用簡寫方式省略類型前綴,例如使用 .start 而不是 MainAxisAlignment.start

// With shorthands
Column(
  mainAxisAlignment: .start,
  crossAxisAlignment: .center,
  children: [ /* ... */ ],
),

// Without shorthands
Column(
  mainAxisAlignment: MainAxisAlignment.start,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [ /* … */ ],
),

類似的還有 .all 而不是 EdgeInsets.all

Padding(
  padding: .all(8.0),
  child: Text('Hello world'),
),

詳細可見我們在之前聊過的 《Flutter 合併 'dot-shorthands' 語法糖》

Web 增強

flutter run 命令現在支持設置 Web 的配置文件,可以在工程根目錄放入 web_dev_config.yaml 來配置 web 主機、端口、證書、headers 等,例如:

server:
  host: "0.0.0.0" # 定義綁定地址
  port: 8080 # 指定開發伺服器的端口
  https:
    cert-path: "/path/to/cert.pem" # 您的 TLS 證書的路徑
    cert-key-path: "/path/to/key.pem" # TLS 證書密鑰的路徑

通過支持代理 (proxy) 設置,還可以將請求轉發到配置的路徑到另一台伺服器:

server:
  proxy:
    -
      target: "http://localhost:5000/" # 您的後端基礎 URL
      prefix: "/users/" # 路徑
    -
      target: "http://localhost:3000/"
      prefix: "/data/"
      replace: "/report/" # 重定向 URL 中路徑的替換 (可選)
    -
      target: "http://localhost:4000/"
      prefix: "/products/"
      replace: ""

最後 3.38 還增強了 Flutter Web 的 hot reload 並默認開啟,當以 -d web-server 參數運行並在瀏覽器打開時,可以支持多個瀏覽器同時連接 hot reload。

當然,和 -d chrome 一樣,您也可以使用 --no-web-experimental-hot-reload 標誌暫時禁用,不過禁用功能將在將來的版本中刪除。

Framework

本次 Framework 調整主要圍繞交互優化相關,比如幫助開發人员可以更精細地控制 UI、導航和平台交互等。

首先是引入了新的 OverlayPortal,允許將子 Widget 渲染在任一 Overlay 上,通過 overlayChildLayoutBuilder 可以更靈活地顯示彈出、對話框、通知等 UI,例如:

class _OverlayPortalExampleState extends State<OverlayPortalExample> {
  final OverlayPortalController _controller = OverlayPortalController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('OverlayPortal')),
      body: Center(
        child: OverlayPortal.overlayChildLayoutBuilder(
          controller: _controller,
          /// ****可以配置 root****
          overlayLocation: OverlayChildLocation.rootOverlay,
          child: ElevatedButton(
            onPressed: () => _controller.toggle(),
            child: const Text('點擊顯示浮層'),
          ),
          overlayChildBuilder: (context, info) {
            return Material(
              elevation: 4,
              color: Colors.white,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
              child: Container(
                padding: const EdgeInsets.all(12),
                child: const Text('這是一個浮層'),
              ),
            );
          },
        ),
      ),
    );
  }
}

通過 overlayChildLayoutBuilder 可以拿到主 Widget 的位置信息,可將浮層顯示在任意螢幕位置,比如按鈕下方、螢幕中心、或與滑鼠位置對齊。

接著是在 Android 平台下,使用 MaterialApp 時默認啟用了預測後退路由轉場 (predictive back route transitions),後退手勢時能看到當前界面預覽,此外默認頁面轉換已從 ZoomPageTransitionsBuilder 更新為 FadeForwardsPageTransitionsBuilder

然後就是久違的 PC 端更新,針對 Windows 桌面開發增強:可訪問已連接顯示器列表,並查詢每個顯示器的解析度、刷新率、物理尺寸等屬性,算是對多窗口模式的增強,例如 PlatformDispatcher.displays 獲取到當前所有顯示器:

void printDisplayInfos() {
  final platformDispatcher = WidgetsBinding.instance.platformDispatcher;
  final displays = platformDispatcher.displays;

  for (final display in displays) {
    final id = display.id;
    final size = display.size; // Size in logical pixels
    final dpr = display.devicePixelRatio;
    final refreshRate = display.refreshRate;
  }
}

同時,現在如果在 Widget 生命週期回調中發生的錯誤(例如 didUpdateWidget)可以更優雅地處理,防止它們在元素樹中導致級聯故障 (#173148),以前如果開發者在這些回調中拋出了異常(哪怕只是一個小錯誤),整個元素樹可能會進入不一致狀態或直接崩潰

而現在 Framework 在這些生命週期階段調用時, 將內部異常捕獲包裝在更安全的範圍內,也就是說,如果你的某個子 Widget 在 didUpdateWidget() 拋出錯誤, Flutter 會:

  • 捕獲這個錯誤;
  • 上報給 Flutter 的全局錯誤處理系統(FlutterError.onError);
  • 允許其他 widget 正常構建;
  • 避免整個 Element Tree 出現「級聯錯誤」(cascade failure)

也就是讓錯誤隔離更強,不再因為一個 widget 的生命週期異常破壞整個界面,而 IDE 中仍然能看到詳細的異常棧,從而讓應用的健壯性顯著提升(尤其對熱重載、動態組件更新等場景)。

最後是一些問題修復,例如:

  • 修復了之前 ResizeImage==hashCode 實現不正確的問題,在之前即使兩個 ResizeImage 指向同一底層圖像和相同尺寸, Flutter 也認為它們不相等
  • 在 Web 上繼續修復 RSuperellipse,以防止在角半徑大於 Widget 本身 (#172254) 時出現渲染錯誤
  • 對於國際用戶來說,檢測瀏覽器的首選區域設置得到優化,引擎現在使用標準的 Intl.Locale Web API 來解析瀏覽器語言,取代了以前的手動實現 (#172964
  • 修復了 Android 的特定錯誤 (#171973),主要影響配備硬體鍵盤的三星設備,以前在用戶與 TextField 互動後,Android 輸入法編輯器 (IME) 可能會陷入過時狀態,導致 IME 錯誤地攔截「Enter」或「Space」鍵按下,從而阻止非文本 Widget (如 複選框單選 按鈕)接收事件,而本次的修復可以確保在文本連接關閉時正確重置 InputMethodManager,清除 IME 的過時狀態,並為用戶還原可預測的硬體鍵盤互動

Material 和 Cupertino 更新

在棄用 MaterialState 的基礎上,3.38 繼續內部遷移到更統一的 WidgetState,這提供了一種更一致的方式來定義控件在不同交互狀態(例如按下、懸停或禁用)中的外觀,並且開發這不需要對現有應用程式碼進行更改。

3.38 開始恰遷移已逐步應用在各種 Widget 及其主題,包括 IconButtonElevatedButtonCheckboxSwitch#173893),新的 API 還增加了功能和靈活性,例如:

  • IconButton 現在包括一個 statesController 屬性 (#169821),允許以編程方式控制其視覺狀態

  • Badge.count 構造函數現在包含一個 maxCount 參數 (#171054),可以限制顯示的計數(例如,顯示「99+」而不是「100」)

  • 為了實現更細粒度的手勢控制,InkWell 現在具有 onLongPressUp 回調 (#173221),可用於觸發僅在用戶抬起手指時才相應完成

  • Cupertino 也繼續朝著更好的 iOS 保真度邁進, CupertinoSlidingSegmentedControl 添加了 isMomentary 屬性 (#164262)以允許控件觸發而不保留選擇,為了更好地匹配原生 iOS 行為,CupertinoSheet 在完全展開時向上拖動時具有微妙的「拉伸」效果 (#168547

  • 修復 DropdownMenuFormField 在窗體重置時正確清除其文本字段 (#174937

  • 更新 SegmentedButton 改進焦點處理 (#173953)並確保其邊框正確反映 Widget 的狀態 (#172754

  • 滾動 (Scrolling) 和 Sliver 系列控件改進,例如 SliverMainAxisGroup / SliverCrossAxisGroup 在複雜滾動佈局中手勢處理、點擊響應、焦點導航更可靠,例如:

    • 對多個 sliver 進行分組的開發人員會發現手勢處理現在更加可靠,現在可以正確計算這些組中細片上的點擊和其他指針事件的命中測試,確保用戶交互按預期運行 (#174265
    • SliverMainAxisGroup 使用固定標題時過度滾動的問題已得到解決 (#173349),調用 showOnScreen 顯示 sliver 現在可以正常工作 (#171339),並且內部滾動偏移量計算更加精確 (#174369)。
    • 對於構建自定義滾動視圖的開發人員來說,新的 SliverGrid.list 構造函數 (#173925) 提供了一種更簡潔的方法,可以從簡單的子列表創建網格
  • 另外還改進了複雜佈局中鍵盤和方向鍵用戶的焦點導航,在具有不同滾動軸的嵌套滾動視圖(例如水平輪播的垂直列表)中,定向焦點導航現在更具可預測性,可防止焦點在部分之間意外跳轉

最後, Material 和 Cupertino 與框架的解耦還在繼續,核心內容就是,解耦後需要作為第一方官方包發布,需要自動化語義化版本管理,避免衝突,支持自定義發布(如跳過特定提交、批量破壞性變更),採用「批量發布」(Batch Release),使用 Cocoon cron job 每週生成合併 PR;開發者通過「commit消息、PR 標籤或獨立 changelog 文件標記變更,首選選項為 PR 獨立 changelog 文件,由 bot 合併等。

另外就是 Widgets 測試不導入 Material/Cupertino;Cupertino 不導入 Material,Material 負責所有多庫導入測試,包括 Cupertino 相容性和自適應等。

以下是一些關於 Material 和 Cupertino 與框架的一些關鍵討論地址:

Accessibility

對於構建複雜應用的開發者,3.38 引入了使用 WidgetsFlutterBinding.instance.ensureSemantics#174163) 在 iOS 上默認打開輔助功能的功能,調試輔助功能問題現在變得更加容易,因為 debugDumpSemanticsTree 包含額外的文本輸入驗證結果信息,以幫助更快地診斷問題 (#174677)。

為了在基於 sliver 的滾動視圖中實現高級可訪問性,3.38 增加了新的 SliverSemantics#167300),與現有的 Semantics 非常相似,開發人員可以在 CustomScrollView 中使用 SliverSemantics 使用特定語義信息註釋其 sliver 樹的某些部分,這對於註釋標題、分配語義角色以及為螢幕閱讀器向 sliver 添加描述性標籤特別有用,從而為用戶提供更易於理解和訪問的體驗。

最後,核心 Widget 的可訪問性不斷完善,現在默認情況下可以訪問 CupertinoExpansionTile#174480),AutoComplete 現在向用戶宣布搜索結果的狀態 (#173480), TimePicker#170060) 中有更大的觸摸目標,有助於提供更易於訪問的開箱即用體驗。

iOS

iOS 平台已經完整支持最新的 iOS 26、Xcode 26、macOS 26,特別是在命令行部署使用 devicectl 替代必須啟動 Xcode App 的流程,現在 Flutter 3.38 可以在大多數情況下僅依賴於 Xcode26 命令行構建工具,更多可見:

雖然官方說完全支持,但是 iOS26 問題還是有的,例如:《來了解一下,為什麼你的 Flutter WebView 在 iOS 26 上有點擊問題?》

另外 Flutter 3.38 包括了對 Apple 強制的 UIScene 生命週期的基本支持,這是繼 Apple 在 WWDC25 上宣布之後的一次關鍵的主動更新:「在 iOS 26 之後的版本中,任何使用最新 SDK 構建的 UIKit 應用都將需要使用 UIScene 生命週期,否則它將不會啟動」。

詳細可見:iOS 26 開始強制 UIScene ,你的 Flutter 插件準備好遷移支持了嗎?,因為適配 UIScene 需要 迁移官方提供了手動遷移和自動遷移的支持,其中自動遷移需要配置 flutter config --enable-uiscene-migration,更多遷移細節可見:docs.flutter.dev/release/bre…

對於 UIScene 支持,更致命的主要還是插件開發者,對於插件作者而言 UIScene 遷移帶來了更大的挑戰:必須確保插件既能在已經遷移到 UIScene 的新應用中正常工作,也要能在尚未遷移的舊應用或舊版 iOS 系統上保持相容,例如:

  • 一個依賴生命週期事件的插件(例如,一個在應用進入後臺時暫停視頻播放的插件)不能簡單地把監聽代碼從 AppDelegate 移到 SceneDelegate,這樣做會導致它在未遷移的應用中完全失效,因此插件必須能夠同時處理兩種生命週期模型
  • 具體插件遷移步驟:
    • 註冊場景事件監聽:在插件的 register(with registrar: FlutterPluginRegistrar) 方法中,除了像以前一樣通過 registrar.addApplicationDelegate(self) 註冊 AppDelegate 事件監聽外,還需要調用新的 API 來註冊 SceneDelegate 事件的監聽,Flutter 提供了相應的機制讓插件可以接收到場景生命週期的回調
    • 實現雙重生命週期處理:插件內部需要實現 UISceneDelegate 協議中的相關方法,在實現時要設計一種優雅降級的邏輯。例如同時實現 applicationDidEnterBackgroundsceneDidEnterBackground,當 sceneDidEnterBackground 被調用時,執行相應邏輯並設置一個標誌位,以避免 applicationDidEnterBackground中的邏輯重複執行(如果它也被意外調用的話)
    • 更新廢棄的 API 調用:插件代碼中任何對 UIApplication.shared.keyWindow 或其他與單一窗口相關的廢棄 API 的調用都必須被替換

Android

升級到 Flutter 3.38 是滿足 Google Play 16 KB 頁面大小相容性要求的重要準備工作, 因為 3.38 的更改可確保你的應用在高 RAM 設備上正常運行,並提供性能優勢,例如啟動速度提高多達 30%。

Flutter 3.38 將默認的 Android ndkVersion 更新為 NDK r28,這是原生代碼實現 16 KB 支持正確對齊所需的最低要求。

Flutter 3.38 還修復(#173770)了影響 Android 上所有 Flutter 應用的嚴重記憶體洩漏,该问题在 3.29.0 中引入,發生在退出時銷毀 Activity 時出現。

對於 Flutter 3.38 版本,Android 環境目前的推薦配置:

  • Java 17:Flutter 3.38 中 Android 開發所需的最低版本
  • KGP 2.2.20:該工具已知且支持的最大 Kotlin Gradle 插件版本
  • AGP 8.11.1:與 KGP 2.2.20 相容的最新 Android Gradle 插件版本
  • Gradle 8.14:此版本適用於所選版本的 Java、KGP 和 AGP,請注意 Gradle 8.13 是 AGP 8.11.1 所需的最低版本。

為確保應用在 Flutter 版本之間無縫運行,強烈建議在構建文件中使用 Flutter SDK 提供的 API 級變數:

  • flutter.compileSdkVersion (API 36)
  • flutter.targetSdkVersion (API 36)
  • flutter.minSdkVersion (API 24) or higher

Engine

performance overlay 已經重構,現在提高效率的同時,減少了 Skia 和 Impeller 後端的渲染時間,這意味著可以以更少的開銷獲得更準確的性能數據。

對 Vulkan 和 OpenGL ES 後端的大量修復和改進提高了更廣泛設備上的穩定性和性能,包括更好地處理管道快取 (#176322)、fence waiters (#173085) 和 image layout transitions (#173884)。

另外對於 Web,繼續統一 CanvasKit 和 Skwasm 渲染器的工作,3.38 包括了它們的重大重構,以在兩者之間共享更多代碼,這將在未來帶來更一致的體驗和更快的開發 (#174588)。

重點重點重點:iOS 和 Android 中已刪除選擇退出執行緒合併的功能。

DevTools 和 IDE

Flutter 3.35 引入了 Widget Previews,而 Flutter 3.38 版本對 Widget Previews 進行了重大改進,包括 VSCode 和 Intellij / Android Studio 插件都已更新,初步支持 Widget Previews ,可以直接在 IDE 中查看預覽

Widget Previews

在 IDE 中使用時,默認情況下 Widget Previews 環境配置為根據當前選定的源文件過濾顯示的預覽:

Widget Previews

另外,Widget Previews 現在支持淺色和深色模式,以及自定義 IDE 配色方案以匹配開發環境,控件預覽環境中的控件也進行了調整,以使用更少的空間,從而為渲染預覽留出更多空間。

Widget Previews

此外,覽註解類不再標記為最終註解,現在可以擴展以創建自定義預覽註解,從而減少常見預覽類型的樣板:

Widget Previews

並且新的 MultiPreview 基類允許從單個自定義註解創建多個預覽變體:

Widget Previews

Preview 類中的新 group 參數允許對相關預覽進行分組,減少了對 @Preview 註解參數的限制,支持私有常量作為 Preview 註解的參數等。

Widget Previews

目前關於預覽還有一些問題,例如 #178317 ,例如 Widget 預覽器可能會在 flutter pub get 後崩潰或停止更新。

其他關於 Tool 更新還有:

  • Flutter DevTools Widget Inspector 正在增加支持適配預覽
  • IDE 中預覽的多專案支持:預覽目前僅支持顯示單個專案或 Pub 工作區中包含的預覽,多專案正在支持
  • 正在推進預覽的性能改進的機會,以減少初始啟動時間
  • Network Panel 的交互改進
  • Flutter Inspector 修復了選擇 Widget 有時會打開底層框架源代碼而不是用戶源代碼的錯誤
  • 修復了 Flutter Inspector 偶爾阻止與「檢查器」面板中的頂部按鈕交互的錯誤

棄用和重大變更

首先,3.38 進行了可能影響自定義生成腳本的關鍵生成和工具更改,Flutter SDK 根目錄的 version 文件已被刪除,取而代之的是位於 bin/cache#172793)中的新 flutter.version.json 文件,此外默認情況下不再生成 AssetManifest.json 文件 (#172594)。

另外還有:

  • 對於 predictable behavior,包含作的 SnackBar 將不再自動關閉 (#173084
  • 前面介紹過的 OverlayPortal.targetsRootOverlay 構造函數已被棄用,取而代之的是更靈活的 OverlayPortaloverlayLocation: OverlayChildLocation.rootOverlay
  • CupertinoDynamicColor 上的幾個屬性(例如 withAlphawithOpacity)現在已棄用,取而代之的是標準 Color 方法
  • Flutter 3.38 要求 Java 17 作為 Android 的最低版本,符合 Gradle 8.14(2025 年 7 月版)的最低要求

最後

本次 3.38 的更新還是挺豐富的,同時也是


原文出處:https://juejin.cn/post/7571693273728696356


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝15   💬3   ❤️3
316
🥈
我愛JS
📝1   💬3   ❤️2
45
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付