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),這將最壞情況下的光柵化時間減少了 2/3 (如我們的基准測試所示),將第 99 百分位的幀時間減少了一半。我們在減少 iOS 卡頓方面取得了持續性的進展,這也是在這條道路上邁出的另一步。然而,着色器預熱只是卡頓的一個來源。在該版本以前,處理來自網絡、文件系統、插件或其他 isolate 的異步事件可能導致動畫中斷,這是另一個卡頓的來源。在該版本中我們對 UI Isolate 的事件循環的調度策略 (#25789) 進行了改進,現在幀處理優先於其他異步事件的處理,在我們的測試中,其導致的卡頓已經被消除。
另一個原因是垃圾回收 (GC) 會暫停 UI 線程來回收內存。在該版本以前,一些圖像的內存只能在 Dart VM 執行 GC 時以較慢的速度進行回收。在早期版本中,常用的做法是 Flutter 引擎會向 Dart VM 提示圖像內存可以通過 GC 回收,理論上可以讓內存回收更為及時。不幸的是,在實踐中這造成了過多的回收,而且內存有時仍然不能被快速回收,導致無法避免在內存有限的設備上出現低內存的情況。在現在的版本中,未使用的圖像的內存會盡可能快速地進行回收 (#26219、#82883、#84740),這大大減少了 GC 的次數。
舉個例子,在我們的一個測試中,播放了一個 20 秒的 GIF 動畫,GC 的次數從需要 400 次下降到只需 4 次。更少的主要 GC,意味着更少的涉及圖像出現和消失的動畫卡頓,更少的 CPU 和電量消耗。
Flutter 2.5 的另一項性能改進是優化了 iOS 上 Dart 和 Objective-C/Swift、Android 上 Dart 和 Java/Kotlin 之間相互通信的延遲。作為 調整消息通道 的一部分,我們從消息編解碼器中移除了不必要的拷貝,在不同內容的大小和設備上減少了高達 50% 的延遲 (詳見 #25988、#26331)。
更多詳情,請你參閱 Aaron Clarke 的文章:提高 Flutter 中的平台通道性能。
如果你要構建 iOS 應用,我們還有最后一項性能更新:在該版本中,使用 Apple Silicon M1 Mac 構建的 Flutter 應用可以直接在 ARM 架構的 iOS 模擬器 (#pull/85642) 上運行。這意味着無需使用 Rosetta 對 Intel x86_64 指令和 ARM 進行轉換,這提升了 iOS 應用測試的性能,並規避了一些微妙的 Rosetta 問題 (#74970、#79641)。這是 Flutter 在全面支持 Apple Silicon 的路程上邁出的又一步,敬請繼續關注。
當然,沒有 Dart 語言和它的運行時環境,就不會有現在的 Flutter,它建立在 Dart 語言和 runtime 之上。Flutter 2.5 同時帶來了 Dart 2.14。新發布的 Dart 版本 不僅帶來了新的格式化使 級聯 操作更加清晰,還帶來了支持忽略文件的新 pub 命令工具,以及新的語言功能 (包括傳說中的無符號右移操作符的回歸)。此外,這個版本帶來了一套新的 Dart 和 Flutter 項目之間共享的標准代碼規范提示,開箱即用,這也是 Dart 2.14 最精彩的部分。
flutter create
開箱即有一個 analysis_options.yaml 文件,預先使用了推薦的 Flutter lint。
當你創建一個新的 Dart 或 Flutter 項目時,你不僅可以使用這些規范,而且 只需要幾個步驟 就可以將這種相同的分析添加到你現有的應用中。關於這些規范的細節、新的語言功能和更多內容,請查閱:Dart 2.14 發布。
Flutter 2.5 版本對框架進行了一些修復和改進。我們修復了關於 Android 全屏模式的一系列相關問題,該 Issue 獲得了上百個點贊,全屏選項包括向后傾斜、沉浸模式、粘性沉浸模式和邊到邊四種。這一變化還增加了一種方法用來監聽其他模式下的全屏變化。例如,如果用戶在使用應用時,改變了系統界面的全屏模式,開發者現在可以通過代碼讓應用重新變為全屏,或執行其他操作。
在這個版本中,我們繼續建立對新的 Material You (又稱 v3) 規范的支持,包括對懸浮按鈕尺寸和主題的更新 (#86441),以及一個新的 MaterialState.scrolledUnder
狀態,你可以通過 PR (#79999) 中的示例代碼看到它的效果。
當我們討論滾動時,另一個改進是增加了額外的滾動指標通知 (#85221、#85499),即使用戶沒有滾動,也會提供可滾動區域的通知。例如,如下示例展示了滾動條根據 ListView 的實際大小而適時出現或消失的效果。
在這種情況下,你不需要寫任何代碼,就可以捕獲 ScrollMetricNotification 的變化。特別感謝社區貢獻者 xu-baolin,他在這方面做了大量工作,並提出了一個很好的解決方案。
社區的另一傑出貢獻是為 ScaffoldMessenger
增加了 Material 橫幅的支持。在 Flutter 2.0 中新增的 ScaffoldMessenger
,它提供了一種強大的方式,在屏幕底部顯示 SnackBars 以向用戶提供通知。在 Flutter 2.5 中,現在你可以在 Scaffold 頂部添加一個橫幅,在用戶將其關閉之前,它將一直保持在原位。
橫幅的 Material 指南 規定你的應用一次只能顯示一個橫幅,所以如果你的應用多次調用 showMaterialBanner
,ScaffoldMessenger
將持有一個隊列,在前一個橫幅被關閉時顯示下一個新的橫幅。感謝 Calamity210 為 Flutter 的 Material 支持提供了有力補充。
在 Flutter 2.0 及其新文本編輯功能的基礎上,我們在這個版本中添加了如文本選擇器、攔截覆寫任何鍵盤事件,以及覆寫文本編輯的鍵盤快捷方式的能力 (#85381)。如果你想讓 Ctrl - A 做一些自定義操作,而不是選擇所有文本,你可以自行定義。DefaultTextEditingShortcuts 類包含了 Flutter 在每個平台上支持的每個鍵盤快捷方式的列表。如果你想覆寫其中的關聯,請使用 Flutter 現有的 Shortcuts widget,將任一快捷鍵重新映射到現有或自定義的意圖,您可以將該 widget 放置在你想要覆寫的地方。示例請參閱:API 文檔。
另一個得到大量改進的插件是 camera 插件:
- 3795 [camera] android-rework 第 1 部分:支持 Android 相機功能的基礎類
- 3796 [camera] android-rework 第 2 部分:Android 自動對焦功能
- 3797 [camera] android-rework 第 3 部分:Android 曝光相關功能
- 3798 [camera] android-rework 第 4 部分:Android 閃光燈和變焦功能
- 3799 [camera] android-rework 第 5 部分:Android FPS 范圍、分辨率和傳感器方向功能
- 4039 [camera] android-rework 第 6 部分:Android 曝光和對焦點功能
- 4052 [camera] android-rework 第 7 部分:Android 降噪功能
- 4054 [camera] android-rework 第 8 部分:最終實現的支持模塊
- 4010 [camera] 在 iOS 上不觸發平放時的設備方向
- 4158 [camera] 修復 iOS 上設置焦點和曝光點的坐標旋轉
- 4197 [camera] 修復相機預覽在設備方向改變時不總是重建的問題
- 3992 [camera] 防止在設置不支持的 FocusMode 時崩潰
- 4151 [camera] 引入 camera_web package
在 image_picker 插件 上也做了很多工作,專注於端到端的相機體驗。
- 3898 [image_picker] 圖像采集器修復相機設備
- 3956 [image_picker] 在 Android 中將相機捕捉的存儲位置改為內部緩存,以符合新的 Google Play 存儲要求
- 4001 [image_picker] 刪除了多余的相機權限請求
- 4019 [image_picker] 修復當相機作為源時的旋轉問題
這些工作改善了 Android 的相機和 image_picker
插件的功能和健壯性。此外,你也許會注意到 camera 插件 的 Web 功能已處於預覽階段 (#4151)。這個預覽版提供了對查看相機預覽、拍攝照片、使用閃光燈和變焦控制的基本支持,所有這些都可以在 Web 上進行。它目前不是一個 被認可的聯合插件,因此在配置中,你需要明確這個插件僅能夠在 Web 應用中 添加使用。
最初的 Android 相機重構工作是由 acoutts 貢獻完成的。camera
和 image_picker
的工作是由 Baseflow 完成的,這是一家專門從事 Flutter 的咨詢公司,因其 在 pub.dev 上的 package 而聞名。camera_web
的工作主要由 Very Good Ventures 完成,這是一家位於美國的 Flutter 咨詢公司。非常感謝你們對 Flutter 社區的貢獻!
另一個有價值的社區貢獻是由 fluttercommunity.dev 組織做出的,他們的代表作是 plus 系列插件。隨着新的 Flutter 版本發布,之前由 Flutter 官方團隊維護的插件現在 “交接” 給了 fluttercommunity.dev 組織,在每個插件下方都會有下面類似的提示:
此外,由於這些插件不再積極維護,所以我們已取消了它們的 Flutter Favorite 標記。如果你還沒有遷移到 plus 系列插件,我們建議你按照以下的表格進行對照遷移。
Flutter 2.5 對 Flutter DevTools 進行了大量的改進。首先是在 DevTools 中增加了對引擎更新的支持 (#26205、#26233、#26237、#26970、#27074、#26617)。其中一組更新使 Flutter 能夠更好地將跟蹤事件與特定的幀聯系起來,這有助於開發人員確定一個幀可能會超出預算的原因。你可以在 DevTools 框架圖中看到這一點,該圖表重構之后已經支持了實時展示;當你的應用正在渲染時,它們的數據會被填入該圖中。從這個圖表中選擇一個構建幀,就可以跳轉到該幀的時間線事件。
Flutter 引擎現在也能識別時間線中的着色器編譯事件。Flutter DevTools 使用這些事件來幫助您診斷應用中的着色器編譯缺陷。
有了這個新功能,DevTools 可以檢測到你因着色器編譯而丟失的構建幀,以幫助你修復這個問題。如果你希望像首次運行應用一樣,使用 flutter run
命令並加上 --purge-persistent-cache
這個標記。這將清除着色器的緩存,以確保你重現用戶在「首次運行」或「重新打開」 (iOS) 應用時看到的效果。此功能仍在開發中,所以請將您發現的 問題或改進建議 提交給我們,以幫助發現和改進着色器編譯工具。
此外,當你追蹤應用中的 CPU 性能問題時,可能已經淹沒在了來自 Dart 和 Flutter 庫或引擎的原生代碼的剖析數據中。如果你想關閉這些數據以專注自己的代碼,那么你可以使用新的 CPU Profiler 功能 (#3236),使你能夠隱藏來自任何這些源的 Profiler 信息。
對於你沒有過濾掉的類別,它們現在已經用顏色進行了分類 (#3310、#3324),這樣你就可以很清晰地看到 CPU 火焰圖內容對應的部分。
性能可能並不是你唯一想要調試的內容。新版本的 DevTools 帶有對 Widget Inspector 的更新,當你將鼠標懸停在 widget 上時,可以評估對象、查看屬性、widget 狀態等等。
而且當你選擇一個 widget 時,它會在新的 Widget Inspector Console 自動彈出,在那里你可以自由探索 widget 的屬性。
當在斷點處暫停時,你也可以在控制台執行表達式。
除了新功能,Widget Inspector 也進行了改頭換面。為了使 DevTools 成為理解和調試 Flutter 應用的最佳工具,我們與芬蘭的創意技術機構 Codemate 合作,進行了一些更新。
如上圖所示,你可以看到以下變化:
- 更好地傳達調試切換按鈕的作用 —— 這些按鈕有新的圖標、面向任務的標簽,以及豐富的工具提示 (用於描述它們的功能和何時使用它們)。每個工具提示都進一步鏈接到了該功能的詳細文檔。
- 更容易查找和定位感興趣的 widget——Flutter 框架中經常使用的 widget 現在已在 Inspector 左側的 widget 樹視圖中作為圖標常駐。它們已經根據其類別使用顏色進行了分類。例如,布局 widget 顯示為藍色,內容 widget 顯示為綠色。此外,每個文本 widget 現在會顯示其內容預覽。
- 更一致的 Layout Explorer 和 widget 樹的顏色方案 —— 現在更容易從 Layout Explorer 和 widget 樹中識別出相同 widget。例如,如上圖所示中的「Column」widget 在 Layout Explorer 中是藍色背景,在 widget 樹視圖中也有一個藍色圖標。
我們很樂意聽到你對這些更新產生的任何 問題和改進建議 以確保 DevTools 高效地運行。這些亮點僅是開始。關於 DevTools 在 Flutter 這個版本中的全部新內容,請查閱以下版本說明:
IntelliJ / Android Studio 的 Flutter 插件在這個版本中也有一些改進,首先改進是運行集成測試的能力 (#5459)。集成測試是在設備上運行的整個應用測試,在 integration_test 目錄下運行,並使用與 widget 單元測試相同的 testWidgets()
功能。
要在您的項目中添加集成測試,請 遵循 flutter.dev 上的說明。要將測試與 IntelliJ 或 Android Studio 連接,請添加一個運行配置,啟動集成測試,並連接一個設備供測試使用。運行配置可以讓你在運行測試的同時,設置斷點、步進等。
此外,Flutter 的最新 IntelliJ / Android Studio 系列插件允許您查看單元測試和集成測試運行的覆蓋率信息。您可以通過「debug」按鈕旁邊的工具欄按鈕來訪問這個信息:
覆蓋率信息將以紅色和綠色的矩形顯示在編輯窗口左側的空隙中。在這個例子里,第 9 - 13 行被測試覆蓋,但第 3 和 4 行沒有被測試。
最新版本還包括預覽來自 pub.dev 的 package 中使用的圖標的新功能,這些 package 是圍繞 TrueType 字體文件構建的 (#5504、#5595、#5677、#5704),正如 Material 和 Cupertino
圖標支持預覽一樣。
要啟用圖標預覽,你需要告訴該插件你正在使用哪些 package。在插件的設置 / 偏好頁面有一個新的文本字段。
注意,這對定義為類中靜態常量的圖標有效,如屏幕截圖中的示例代碼所示。它不會對表達式起作用,例如 LineIcons.addressBook()
或 LineIcons.values['code']
。如果你是一個圖標 package 的作者,而這個圖標 package 並不適合這個功能,請 創建一個 Issue 進行反饋。
更多有關 Flutter 的 IntelliJ / Android Studio 插件的更新信息,請參閱下列發布說明:
- Flutter IntelliJ Plugin M57 發布
- Flutter IntelliJ Plugin M58 發布
- Flutter IntelliJ Plugin M59 發布
- Flutter IntelliJ Plugin M60 發布
Flutter 的 Visual Studio Code 插件在這個版本中也得到了改進,首先是兩個新的命令「Dart: Add Dependency」和「Dart: Add Dev Dependency」 (#3306、#3474)。
這些命令提供的功能與已經提供了一段時間的 Jeroen Meijer 的 Pubspec Assist 插件 類似。這些新命令開箱即用,提供了一個從 pub.dev 定期獲取的 package 的類型過濾列表。
你可能還對「Fix All」命令感興趣 (#3445、#3469),該命令對 Dart 文件可用,可以在一個步驟中修復所有與 dart fix 相同的問題。
你也可以在 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 VS Code Test Runner 集成,Flutter 創建設置,...
- v3.25 額外的依賴性管理改進,在文件 / 保存時修復所有,...
- v3.24 依賴關系樹的改進,更容易啟動配置,編輯器的改進
- v3.23 配置文件模式的改進,改進依賴關系樹,改進 LSP
在以前的 Flutter 版本中,你可能會被那些你不希望處理的異常所困擾,你可能希望它們觸發調試器並找出它們的源頭,但卻發現 Flutter 框架沒有讓異常通過來觸發調試器中的「未處理的異常」處理程序。在這個版本中,調試器現在可以正確地中斷未處理的異常,而以前這些異常只是被框架捕獲 (#17007)。這改善了調試的體驗,調試器現在可以直接指向異常在代碼中的拋出行,而不是指向框架深處的一個隨機位置。與之相關的一個新功能是你能夠決定 FutureBuilder 是否應該重新拋出或隱藏錯誤 (#84308)。這應該會給你提供更多的異常,以幫助你追蹤 Flutter 應用中的問題。
自從 Flutter 誕生以來,就有了 Counter 應用模板,它有很多優點:它展示了 Dart 語言的很多特性,演示了幾個關鍵的 Flutter 概念,而且它足夠小,即使有很多解釋性的注釋,也能裝進一個文件。然而,它並未對 Flutter 應用的實際使用場景提供一個特別好的展示。在這個版本中,你可以通過以下命令創建一個新的模板 (#83530)。
$ 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 插件頁面 找到更多信息。
以下是 Flutter 2.5 版本中的破壞性改動:
- 默認的設備拖動和滾動
- v2.2 版后刪除了廢棄的 API
- Package 介紹: flutter_lints
- ThemeData 的 accent 屬性已被棄用
- 手勢識別器清理
- 將 AnimationSheetBuilder.display 替換為 collate
- 使用 HTML 插槽在 Web 中渲染平台視圖
- 將 LogicalKeySet 遷移至 SingleActivator
了解自 1.17 版本以來完整的破壞性改動列表,請參閱:Flutter 文檔網站。
隨着我們繼續更新 Flutter Fix (可在 IDE 中使用,也可通過 dart fix
命令使用),我們總共應用了 157 條規則,來遷移受破壞性改動以及任何棄用影響的代碼。一如既往,我們非常感謝社區 提供的測試,幫助我們識別了這些破壞性改動。如需了解更多,請查閱: Flutter 破壞性改動政策。
另外,隨着 Flutter 2.5 的發布,我們將放棄對 iOS 8 的支持,正如 2020 年 9 月宣布 的那樣。放棄對市場份額不足 1% 的 iOS 8 的支持,使 Flutter 團隊能夠專注於使用范圍更廣的新平台。棄用意味着這些平台可能可以正常使用 Flutter,但我們不會在這些平台上測試新版本的 Flutter 或插件。您可以在 Flutter 文檔網站 上看到 目前 Flutter 支持的平台列表。
最后,一如既往地感謝世界各地的 Flutter 社區組織和社區成員們,是社區讓這一切成為可能。在本次更新中貢獻和審核 1000 多個 PR 的數百位開發者,因為有你們每個人的努力才成就了本次的成果。讓我們攜手共同努力,為世界各地的開發者共同轉變應用的開發流程,讓開發者們可以從一個代碼庫中交付更多應用、更快開發、部署到更多你所關心的平台。
敬請關注 Flutter 團隊的更多更新,這一年還沒有結束,拭目以待!
感謝 flutter.cn 社區成員 (@AlexV525、@Vadaski、@MeandNi) 以及 Yuan 和 Lynn 對本文的審校和貢獻。