0%

【文章內容使用 Gemini 1.5 Pro 自動產生】

過去幾年,我一直對「如何讓 Flutter 與其主機平台之間的通訊更快、更容易?」這個問題感到興趣。這對 Flutter Plugin 開發人員和增加到應用程式開發人員來說,是一個特別感興趣的問題。

Flutter 與主機平台之間的通訊通常使用 [平台通道](https://flutter.dev/docs/development/platform-integration/platform-channels) 完成,因此我的精力一直集中在這裡。在 2019 年後期,為了解決使用平台通道所需的過多樣板和 [字串類型](https://wiki.c2.com/?StringlyTyped) 程式碼,我設計了一個程式碼產生套件 [Pigeon](https://pub.dev/packages/pigeon),它使平台通道類型安全,並且團隊持續改進它。在 2020 年春季,我對 [平台通道和外部函式介面 (FFI) 效能進行了審查](https://docs.google.com/document/d/1bD_tiN987fWEPtw7tjXHzqZVg_g9H95IS32Cm609VZ8/edit)。現在,我將目光放在 [改進平台通道的效能](https://docs.google.com/document/d/1oNLxJr_ZqjENVhF94-PqxsGPx0qGXx-pRJxXL6LSagc/edit?usp=sharing) 上。由於 Pigeon 建立在平台通道之上,而我計畫在 Pigeon 之上建立一個 [多個 Flutter 實例的資料同步解決方案](http://flutter.dev/go/data-sync),這是一個很好的機會,可以幫助滿足開發人員的許多不同需求,以及我的計劃。

經過一番調查,我能夠識別出透過平台通道傳送的資料的冗餘副本,並且能夠將其移除。您將在下面找到該變更的結果以及識別和移除這些副本的相關工作概述。

結果

在移除透過平台通道從 Flutter 傳送到主機平台的 1 MB 二元資料時,並響應 1 MB 的資料,我們看到 [iOS 上的效能大約提高了 42%](https://flutter-flutter-perf.skia.org/e/?begin=1620764044&end=1621044607&queries=sub_result%3Dplatform_channel_basic_binary_2host_1MB%26test%3Dmac_ios_platform_channels_benchmarks_ios&requestType=0)。在 Android 上,結果稍微複雜一些。我們的自動化效能測試 [大約提高了 15%](https://flutter-flutter-perf.skia.org/e/?begin=1621972627&end=1622677144&queries=sub_result%3Dplatform_channel_basic_binary_2host_1MB%26test%3Dlinux_platform_channels_benchmarks&requestType=0),而本地測試在遷移到新的 [BinaryCodec.INSTANCE_DIRECT](https://github.com/flutter/engine/blob/b3ebb6dd62cefe3c30a7bd15ed73c578030140e2/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java#L27) 編碼器時,[大約提高了 52%](https://github.com/flutter/engine/pull/26331#issuecomment-854071096)。這種差異可能是因為自動化效能測試在舊設備上運行,但也可能是微基準測試在舊設備上的執行方式產生的假象(例如,不斷地讓垃圾收集器執行)。您可以在 [platform_channels_benchmarks/lib/main.dart](https://github.com/flutter/flutter/blob/00bfe9061369bb6fdfe4a74fb27086b77df107bf/dev/benchmarks/platform_channels_benchmarks/lib/main.dart#L165) 中找到自動化效能測試的原始碼。

對於使用 StandardMessageCodec 的平台通道,我發現效能增益較小([使用 14k 負載大約為 5%](https://flutter-flutter-perf.skia.org/e/?begin=1620764044&end=1621044607&queries=sub_result%3Dplatform_channel_basic_standard_2host_large%26test%3Dmac_ios_platform_channels_benchmarks_ios&requestType=0))。我使用一個大型支援類型陣列對其進行測試,以對編碼和解碼進行壓力測試。我發現,MessageCodecs 的編碼和解碼時間遠遠超過在平台之間複製訊息所花費的時間。大部分的編碼時間都是由於對資料結構進行遞迴,並使用反射來找出其內容的成本所致。

因此,根據您使用平台通道的方式和設備,您的結果可能會有很大差異。如果您想要使用平台通道進行最快的通訊,那麼您應該使用 BasicMessageChannels,並在 iOS 上使用 [FlutterBinaryCodec](https://github.com/flutter/engine/blob/b3ebb6dd62cefe3c30a7bd15ed73c578030140e2/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h#L52),在 Android 上使用 [BinaryCodec.INSTANCE_DIRECT](https://github.com/flutter/engine/blob/b3ebb6dd62cefe3c30a7bd15ed73c578030140e2/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java#L27),並為編碼和解碼訊息開發自己的協定,該協定不依賴於反射。(實作新的 MessageCodec 可能更乾淨。)

如果您想試用新的、更快的平台通道,它們現在已在 [master 通道](https://flutter.dev/docs/development/tools/sdk/upgrading#switching-flutter-channels) 上提供。

詳細複製移除

如果您對如何實現這些結果以及我必須克服的問題不感興趣,那麼現在就可以停止閱讀了。如果您喜歡了解詳細資訊,請继续阅读。

平台通道 API 自 2017 年以來沒有太大變化。由於平台通道是引擎和 Plugin 操作的基礎,因此它們不容易更改。雖然我對平台通道的運作方式有一定的了解,但它們在一定程度上是複雜的。因此,改進其效能的第一步是準確地了解它們的運作方式。

下圖概述了框架在使用平台通道與 iOS 進行通訊時從 Flutter 遵循的原始流程:

圖表中的一些收穫:

  • 訊息會從 UI 線程跳轉到平台線程,然後再跳回 UI 線程。(在 Flutter 引擎術語中,UI 線程是執行 Dart 的位置,而平台線程是主機平台的主線程。)
  • 訊息及其響應使用 C++ 作為介於 Flutter 與主機平台目標語言之間的介面層。
  • 訊息的資訊在到達 Objective-C (Obj-C) 處理程式之前被複製了 4 次(步驟 3、5、7、8)。步驟 3 和 8 執行翻譯,而步驟 5 和 8 執行複製,將資料的所有權轉移到新的記憶體佈局。相同的過程反向重複以進行回覆。
  • 步驟 1、9 和 16 是使用 Flutter 的開發人員編寫的程式碼。

從 Flutter 傳送訊息到 Java/Kotlin 類似,只是在 C++ 和 Java 虛擬機器 (JVM) 之間有一個 Java 本機介面 (JNI) 層。

在確定平台通道的運作方式後,很明顯,消除在這些層之間傳輸資料時進行的複製(例如,從 C++ 到 Obj-C)是改進效能的顯而易見的方法。為了實現這一點,Flutter 引擎必須將資料放置在記憶體中,以使其可以直接從 Java/Obj-C 存取,並且具有與主機平台相容的記憶體管理語義。

平台通道訊息最終由主機平台的 MessageCodec 的 decodeMessage 方法使用。在 Android 上,這意味著一個 [ByteBuffer](https://github.com/flutter/engine/blob/58459a5e342f84c755919f2ad5029b22bcddd548/shell/platform/android/io/flutter/plugin/common/MessageCodec.java#L38),在 iOS 上,這意味著一個 [NSData](https://github.com/flutter/engine/blob/58459a5e342f84c755919f2ad5029b22bcddd548/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h#L38)。C++ 中的資料必須符合這些介面。在處理此問題時,我發現訊息的資訊儲存在 C++ 記憶體中,作為一個 [std::vector](https://github.com/flutter/engine/blob/70ebfc3610c38c463469ffedea85578f35ccc0a0/lib/ui/window/platform_message.h#L39),位於由 [共用指標](https://en.wikipedia.org/wiki/Smart_pointer) 維護的 PlatformMessage 物件中。這意味著開發人員在將資料從 C++ 傳送到主機平台時,無法安全地移除複製,因為他們沒有保證資料在傳送到主機平台後不會被 C++ 變異。此外,我必須小心,因為 BinaryCodec 實作將 encodeMessage 和 decodeMessage 視為無操作,這可能導致使用 BinaryCodec 的程式碼在不知情的情況下收到直接 ByteBuffer。雖然有人可能會對 MessageCodec 的變更感到意外,但很少有人實作自己的編碼器。另一方面,使用 BinaryCodecs 非常普遍。

在閱讀程式碼後,我發現,雖然 PlatformMessage 由共用指標管理,但它在語義上是唯一的指標。目的是一次只允許一個客戶端存取它(這並不完全是這樣,因為在線程之間傳遞 PlatformMessage 時,暫時會存在多個副本,但这僅僅是为了方便,而并非真正意图)。這意味著我們可以從共用指標遷移到唯一指標,允許我們安全地將資料傳遞到主機平台。

在 [遷移到唯一指標](https://github.com/flutter/engine/commit/7424400f07be684bd87633bbe2d263821181345a#diff-d5a1c9b29bed0d80dc68f228550643925a216e65173364e1ae5a03067b60160d) 後,我必須找到一種方法,將資訊的所有權從 C++ 傳遞到 Obj-C。(我首先實作了 Obj-C,稍後將更詳細地討論 Java)。資訊儲存在一個 std::vector 中,它沒有辦法釋放底層緩衝區的所有權。您唯一的选择是复制出数据、提供一个包含std::vector的适配器、或消除std::vector的使用。

我的第一次嘗試是子類化 NSData,它會 std::move std::vector 並從那裡讀取其資料,從而消除複製。這種嘗試效果不佳,因為結果證明 NSData 是 [Foundation](https://developer.apple.com/documentation/foundation?language=objc) 中的 [類別叢集](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ClassClusters/ClassClusters.html)。這意味著您不能只子類化 NSData。在閱讀了許多 Apple 的文件之後,他們似乎建議使用組合和訊息轉發,使物件的行為和外觀像 NSData 一樣。這會欺騙使用代理物件的人,除了那些呼叫 -[NSObject isKindOfClass:] 的人以外。雖然這不太可能,但我無法排除這種可能性。雖然我認為可能有一些與 Obj-C 執行時相關的調整,可以使物件按照我想要的方式運行,但它變得越來越複雜。我選擇將記憶體從 std::vector 移動到 [我們自己的緩衝區類別](https://github.com/flutter/engine/commit/b0bb8eab1d2f7e58230298c28a28ddfeddedeb64#diff-d5a1c9b29bed0d80dc68f228550643925a216e65173364e1ae5a03067b60160d) 中,該類別允許釋放資料的所有權。這樣,我就可以使用 -[NSData dataWithBytesNoCopy:length:] 將資料的所有權傳遞到 Obj-C。

在 Android 上複製這個過程證明更困難。在 Android 上,平台通道符合 ByteBuffer,它具有 [直接](https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html) [ByteBuffers](https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html) 的概念,允許 Java 程式碼直接與以 C/C++ 方式佈局的記憶體進行介面。我在短時間內實作了遷移到直接 ByteBuffers,但我沒有看到預期的改進。我花費了很長時間學習 Android 分析工具,最終選擇了追蹤語句,因為那些工具失敗了,或者返回了我無法相信的結果。事實證明,從平台線程到 UI 線程排程對平台通道訊息的回覆非常慢,而且似乎慢到這種程度,這種減速程度會隨著訊息的負載而增加。長話短說,我在編譯 Dart VM 時使用了錯誤的編譯標誌,以為 -no-optimization 代表 -no-link-time optimization,但該標誌實際上是針對運行時優化的。

在我發現自己的錯誤時,我忘記了在將資料傳送到 Flutter 客戶端程式碼(特別是透過自訂 MessageCodecs 或 BinaryCodec 的客戶端)時使用直接 ByteBuffer 的後果。傳送直接 ByteBuffer 意指您有一個 Java 物件正在與 C/C++ 記憶體進行通訊,因此,如果您刪除 C/C++ 記憶體,那麼 Java 會與隨機垃圾進行交互,並且可能會因作業系統的存取衝突而當機。

效仿 iOS 的做法,我嘗試將 C/C++ 記憶體的所有權傳遞給 Java,以便在 Java 物件被垃圾收集時,它會刪除 C/C++ 記憶體。結果證明,當直接 ByteBuffer 是透過 JNI 透過 [NewDirectByteBuffer](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#NewDirectByteBuffer) 建立時,這是做不到的。JNI 沒有提供在 Java 物件刪除時得知的掛鉤。您無法子類化 ByteBuffer,以便在它被終止時呼叫 JNI。唯一的希望是在上圖中的步驟 5 中從 Java API 分配直接 ByteBuffer。透過 Java 分配的直接 ByteBuffers 沒有這個限制。但是,在 Java 中引入新的入口點將是一個巨大的變革,而且任何使用過 JNI 的人都知道這是很危險的。

相反,我選擇請團隊接受在 decodeMessage 呼叫中使用直接 ByteBuffers。起初,我在 MessageCodec 中引入了一個新的方法,bool wantsDirectByteBufferForDecoding(),以確保沒有人獲得直接 ByteBuffer,除非他們請求它,並且知道其語義(也就是,當底層 C/C++ 記憶體仍然有效時)。這被證明是複雜的,並且令人擔憂的是,開發人員可能會訂閱,但不知道直接 ByteBuffers 的語義,因為它們的運作方式與典型的 ByteBuffers 相反,可能會在他們身下刪除其 C 記憶體支援。儲存編碼的緩衝區是不尋常的使用方式,而且不太可能使用,但團隊無法排除這種可能性。經過多次討論和協商,我們決定每個 MessageCodec 都會獲得一個直接 ByteBuffer,在呼叫 decodeMessage 後會被清除。這樣,如果有人快取編碼的訊息,那麼如果他們在底層 C 記憶體被清理後嘗試使用 ByteBuffer,他們就會在 Java 中得到一個確定性的、適當的錯誤。

讓每個人都能獲得直接 ByteBuffers 效能提升的優點效果很好,但這對 BinaryCodec 來說是一個重大變革,其 encodeMessage 和 decodeMessage 實作是無操作的,它們只是將輸入作為返回值轉發。為了保持 BinaryCodec 的相同記憶體語義,我引入了一個 [新的實例變數](https://github.com/flutter/engine/blob/01d1ed459a313f19e2e01cf8d62331d19b907637/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java#L29),它控制解碼的訊息是直接 ByteBuffer(新的、更快的程式碼)還是標準 ByteBuffer(舊的、更慢的程式碼)。我們無法建立一種方法,讓 BinaryCodec 的所有客戶端都能獲得效能提升。

未來工作

現在已經消除了複製,我下一步改進 Flutter 與主機平台之間通訊的努力是:

  1. 為 Pigeon 實作自訂 MessageCodec,該編碼器不依賴於反射,以實現更快的編碼和解碼。
  2. 實作 FFI 平台通道,讓您可以在不跳轉 UI 和平台線程之間的情況下,從 Dart 呼叫主機平台。

我希望您喜歡這次對此效能改進的詳細資訊的深入探討!


改進 Flutter 中的平台通道效能 最初發表在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 2.2 新功能

Flutter 2.2 版本專注於完善和優化,包括 iOS 效能改進、Android 延遲組件、更新的 Flutter Web 服務工作者等等!

今天,我們正式發佈 Flutter 2.2。您可以透過切換到 stable channel 並升級您目前的 Flutter 安裝,或前往 flutter.dev/docs/get-started 開始新的安裝來取得它。

儘管距離 Flutter 2 發佈只有幾個月,但我們在 2.2 版本中有很多改進要分享。此版本合併了框架、引擎和 Plugin 儲存庫中的 2,456 個 PR 並解決了 3,105 個問題。特別感謝廣大的 Flutter 社群,他們提供了大量的 PR 和 PR 審查,包括貢獻最多 PR(17 個)的 Abhishek01039 和審查最多 PR(9 個)的 xu-baolin,他們為 Flutter 2.2 做出了貢獻。感謝所有貢獻者幫助將 Flutter 2.2 帶入 stable channel。沒有您的協助,我們無法做到。

隨著每個新的 Flutter 版本穩定發佈,都會有一系列新的更新,無論是效能增強、新功能還是錯誤修復。此外,發佈版本還包含一些尚未準備好投入生產使用的功能,但我們希望您能夠驗證它們是否按您的預期運作。最後,每個新版本都帶有一組相關的工具更新和來自更廣泛的 Flutter 社群的更新。老實說,如今每次 Flutter 新版本發佈時都會發生很多事情,我們不可能在一篇部落格文章中涵蓋所有內容,但我們會盡力突出重點。

穩定版 Flutter 2.2 更新

此版本在 Flutter 2 的基礎上涵蓋了廣泛的改進,包括 Android、iOS 和 Web 的更新,新的 Material 圖示、文字處理更新、捲軸行為和 TextSpan Widget 的滑鼠游標支援,以及有關如何從單一原始碼庫最佳支援多種平台的新指南。所有這些功能現在都可以在 stable 版本中使用,您可以用於生產應用程式。所有這些功能都建立在新的 Dart 版本之上。

Dart 2.13

Flutter 2.2 與 Dart 2.13 版本一起發佈。除了其他功能外,此 Dart 更新還包含一個新的類型別名功能,使您能夠為類型和函數建立別名:

類型別名使您能夠為長而複雜的類型提供簡潔的短名稱,它還讓您以非破壞性的方式重新命名類別。Dart 2.13 中還有更多新功能;在 Dart 2.13 發佈公告 中查看詳細資訊。

Flutter Web 更新

Flutter 最新的穩定平台 Web 在此版本中得到了改進。

首先,我們使用新的服務工作者載入機制優化了快取行為,並修復了 main.dart.js 的重複下載問題。在以前的 Flutter Web 版本中,服務工作者在向使用者提供應用程式的舊版本時,會在背景中下載應用程式的更新。下載更新後,使用者必須刷新瀏覽器頁面幾次才能看到這些更改。從 Flutter 2.2 開始,當新的服務工作者偵測到更改時,使用者將等待更新下載才能使用應用程式,但他們將看到更新,而無需再次手動刷新頁面。

若要啟用此更改,您需要重新產生 Flutter 應用程式的 index.html 檔案。若要執行此操作,請儲存您的修改,刪除 index.html 檔案,然後在您的專案目錄中執行 flutter create . 以重新建立它。

我們還對兩個 Web 渲染器都進行了改進。對於 HTML,我們加入了對 字體功能 的支援,以啟用設定 FontFeature 以及使用畫布 API 渲染文字,以便在懸停時文字顯示在正確的位置。對於 HTML 和 CanvasKit,我們加入了對著色器遮罩和 computeLineMetrics 的支援,解決了 Flutter Web 和行動應用程式之間的奇偶性差距。例如,開發人員現在可以使用 不透明遮罩 透過著色器遮罩執行淡出轉場,並像在行動應用程式中一樣使用 computeLineMetrics

對於 Flutter Web 以及 Flutter 本身,無障碍功能是我們的首要任務之一。按照設計,Flutter 透過建立 SemanticsNode 樹來實作無障碍功能。當 Flutter Web 應用程式使用者啟用無障碍功能時,框架會產生一個與 RenderObject DOM 樹平行的 DOM 樹,並將語義屬性轉換為 Aira。在此版本中,我們改進了語義節點位置,以在使用轉換時縮短行動和桌面 Web 應用程式之間的差距,這意味著當 Widget 透過轉換進行樣式設定時,焦點框應正確顯示在元素之上。若要實際查看此功能,請查看 Victor Tsaran 的這個影片,他在影片中使用 VoiceOver 和 Flutter Gallery App:

我們還透過命令列標誌在配置文件和發行模式下公開了語義節點除錯樹,以幫助開發人員透過視覺化為其 Web 應用程式建立的語義節點來除錯無障碍功能。

若要為您自己的 Flutter Web 應用程式啟用此功能,請執行以下操作:

1
2
$ flutter run -d chrome --profile 
--dart-define=FLUTTER_WEB_DEBUG_SHOW_SEMANTICS=true

啟用該標誌後,您將可以在 Widget 上方看到語義節點,這讓您能夠除錯並查看語義元素是否放置在不應放置的位置。如果您發現此類範例,請隨時 提交錯誤報告

雖然我們在支援一組核心無障碍功能方面取得了重大進展,但我們將繼續改進無障碍功能支援。在 2.2 穩定版本之後,在 master 和 dev channel 上提供的版本中,我們加入了一個 API,讓開發人員可以透過程式設計方式 自動啟用應用程式的無障碍功能,並且正在修復 使用螢幕閱讀器與 Tab 鍵 的問題。

最後,但同樣重要的是,最新版本的 Flutter DevTools 現在支援 Flutter Web 應用程式的佈局瀏覽器。

此更新為您提供了與行動和桌面應用程式相同的佈局除錯工具。

iOS 頁面轉場和增量安裝

對於 iOS,在此版本中,我們 在 Cupertino 中使頁面轉場更加流暢,透過將渲染動畫畫面的時間縮短 75%,而在低端手機上可能會縮短更多時間。我們不僅尋找最終使用者效能的改進;我們始終在尋找改進開發效能的方法。

在此版本中,我們 在開發過程中實作了增量 iOS 安裝。在我們的基準測試中,我們發現安裝更新版本的 iOS 應用程式所需的時間減少了 40%,這減少了測試應用程式更改時的週轉時間。

使用 Flutter 建立平台適應性應用程式

隨著 Flutter 在 stable 版本中擴展到支援更多平台,考慮支援不同外觀尺寸(例如行動裝置、平板電腦和桌面),以及不同輸入類型(觸控 vs. 滑鼠 + 鍵盤)和具有不同慣例的平台(例如導航抽屜 vs. 系統選單用於導航)的應用程式變得很有用。我們將能夠根據不同目標平台的細節進行調整的應用程式稱為「平台適應性」應用程式。

對於在建立平台適應性應用程式時需要牢記的考量,我們建議您參考 Kevin Moore 的 建立平台適應性應用程式 議程。若要更詳細地查看,請查看 flutter.dev 上的平台適應性應用程式指南

最後,對於根據這些原則為多個平台編寫的範例應用程式,我們建議您使用 gSkinner 的 FlokkFlutter Folio 應用程式。您可以下載 FlokkFolio 的程式碼,以及從各個應用程式商店下載 FlokkFolio,或直接從瀏覽器中執行它們。另一個很棒的範例是是用於建立指南本身的應用程式:

Flutter 平台適應性應用程式指南的 UX 部分是基於新的 Material 大型螢幕指南。Material 團隊的這項新指南包括重新設計多個主要佈局文章,以及更新多個元件和更新的設計工具包,所有這些都是針對大螢幕進行的。

Flutter 的目標一直是啟用不僅可以在多個平台上執行,而且在所有目標平台上都能 出色 執行的應用程式。Flutter 擁有您需要的支援,不僅可以將應用程式定位到多個平台,而且還打算為每個平台的螢幕大小、輸入模式和慣例 量身打造 您的應用程式。

更多 Material 圖示

談到 Material 指南,在此版本中,我們不僅加入了一個,而是 兩個 獨立的 PR,為 Flutter 加入新的 Material 圖示,包括 Dash 本人的圖示!

這些更新使您的應用程式可用的 Material 圖示總數增加到 7,000 多個。如果您在這麼多豐富的圖示中找不到您要尋找的圖示(誰會呢?),您可以在 fonts.google.com/icons 根據類別和名稱搜尋。

根據名稱搜尋 Flutter Material 圖示

找到完美的圖示後,新的「Flutter」標籤會顯示如何使用它,或者您可以僅下載該圖示以作為獨立資產用於您的應用程式中。將 Dash 加入您的 Flutter 應用程式中從未如此簡單。

改進的文字處理

隨著我們繼續改進 Flutter 以支援每個平台的細節,我們繼續推進到在行動外觀尺寸上並不那麼重要,但在桌面外觀尺寸上很重要的新領域。其中一個領域是文字處理。在此版本中,我們已開始重構處理文字輸入的方式,以啟用取消鍵盤輸入(當鍵盤輸入透過 Widget 階層級別傳播時)、以及透過引入能夠完全自訂與文字動作相關的鍵盤輸入的能力。

能夠取消鍵盤輸入讓 Flutter 能夠實作使用空格鍵和箭頭鍵而不會觸發捲軸事件的功能,為您的最終使用者提供更直观的體驗。您可以在自己的應用程式中使用相同的功能來處理鍵盤輸入,然後再輸入到父 Widget 中。另一個範例是,在此版本中,您可以在 Flutter 應用程式中的 TextField 和按鈕之間按 Tab 鍵,並且它可以正常運作:

Flutter 2.2 可以取消鍵盤輸入從 Widget 階層級別向上傳播,例如允許 TAB 將焦點從 TextField 切換

自訂文字動作允許您執行諸如在 TextField 中對 Enter 鍵進行特殊處理之類的操作;例如,您可以觸發在聊天客戶端中發送訊息,同時仍然允許透過 Ctrl+Enter 插入換行符。這些相同的文字動作 讓 Flutter 本身能夠提供不同的鍵盤輸入,以將文字編輯的行為與主機作業系統本身相匹配,例如 Windows 和 Linux 上的 Ctrl+C,但 macOS 上的 Cmd+C。

舉例來說,以下範例覆蓋了預設的左箭頭動作,並為退格鍵和刪除鍵提供了一個新的動作:

不可饒恕的 TextField 範例,其中按下左箭頭或 ESC 鍵會清除文字

我們還有更多工作要做,但我們正在努力為您提供完整的文字編輯動作。我們的目標是,當 Flutter 桌面到達 stable 版本時,您的使用者將無法區分在 Flutter 應用程式和主機作業系統上的任何其他應用程式中編輯文字。

自動捲軸行為

作為我們不斷努力讓 Flutter 應用程式像每個平台上最好的應用程式一樣運作的一部分,我們在此版本中再次查看了捲軸條。在實際顯示捲軸條方面,Android 和 iOS 都是一樣的;預設情況下,它們不會顯示捲軸條。另一方面,對於桌面應用程式,當內容比容器大時,通常會自動顯示捲軸條,這需要您加入 Scrollbar 父 Widget。若

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

宣布 Flutter 2.2:領先的多平台 UI 工具組的持續發展

在今天的 Google I/O 上,我們宣布了 [Flutter 2.2](https://flutter.dev/docs/whats-new),這是我們開源工具組的最新版本,可以用於從單一平台建立適用於任何設備的精美應用程式。Flutter 2.2 是迄今為止最佳的 Flutter 版本,它提供了更新,使開發人員比以往更容易透過應用程式內購買、付款和廣告來獲利;連接到擴展應用程式以支援新功能的雲端服務和 API;以及工具和語言功能,讓開發人員能夠消除一整類錯誤,提高應用程式效能,並縮減套件大小。

建立在 Flutter 2 的基礎之上

Flutter 2.2 建立在 Flutter 2 的基礎之上,Flutter 2 將 Flutter 從行動端擴展到包含 Web、桌面和嵌入式使用。它專為環境計算世界而設計,在環境計算世界中,使用者擁有各種不同的設備和外形尺寸,並希望獲得跨越他們日常生活的連貫體驗。有了 Flutter 2.2,企業、新創公司和企業家都可以建立高品質的解決方案,這些方案可以發揮其可尋址市場的全部潛力,讓創意靈感(而非目標平台)成為唯一的限制因素。

Flutter 現在是跨平台開發最受歡迎的框架。

最近的一項行動開發人員研究突顯了 Flutter 的成長。分析公司 [SlashData](https://www.slashdata.co/) 的 [2021 年行動開發人員人口預測](https://www.slashdata.co/reports/?category=mobile-desktop) 顯示,Flutter 現在是跨平台開發最受歡迎的框架,45% 的開發人員選擇使用它,從 2020 年第一季到 2021 年第一季成長了 47%。我們自己的數據證實了這種向 Flutter 的轉變;在過去 30 天中,Play 商店中超過八分之一的新應用程式都是使用 Flutter 建立的。

在 I/O 上,我們分享了現在僅在 Play 商店中就有超過 20 萬個應用程式是使用 Flutter 建立的。這些應用程式來自像騰訊這樣的公司,其 [微信](https://apps.apple.com/us/app/wechat/id414478124) 通訊應用程式在 iOS 和 Android 上擁有超過 12 億使用者;[字節跳動](https://www.bytedance.com/en/products/),TikTok 的創始人,他們現在已經使用 Flutter 建立了 70 個不同的應用程式;以及其他來自包括 [BMW](https://www.press.bmwgroup.com/global/article/detail/T0328610EN/the-my-bmw-app:-new-features-and-tech-insights-for-march-2021?language=en)、[SHEIN](https://apps.apple.com/app/id878577184)、[Grab](https://apps.apple.com/app/id647268330) 和 [DiDi](https://play.google.com/store/apps/details?id=com.xiaojukeji.didi.global.customer&hl=None) 等公司的應用程式。當然,Flutter 不僅僅被大型企業使用。一些最具創新性的應用程式來自您可能從未聽說過的名字:例如,[Wombo](https://play.google.com/store/apps/details?id=com.womboai.wombo&hl=None),病毒式的唱歌自拍應用程式;[Fastic](https://play.google.com/store/apps/details?id=de.fastic.app&hl=None),間歇性禁食應用程式;以及 [Kite](https://play.google.com/store/apps/details?id=com.zerodha.kite3&hl=None),一個精美的投資交易應用程式。

介紹 Flutter 2.2

Flutter 2.2 版本重點改進開發體驗,幫助您為客戶提供更可靠、更高效能的應用程式。

聲明性空安全現在是新專案的預設值。空安全增加了對空引用異常的保護,讓開發人員能夠在程式碼中表達非空類型。由於 Dart 的實作是 *聲明性的*,編譯器可以在執行時消除空檢查,為您的應用程式提供更高的效能。生態系統迅速做出回應,大約有 5,000 個套件已經更新以支援空安全。

此版本中也包含許多效能改進:對於 Web 應用程式,我們提供了使用服務工作者的背景快取;對於 Android 應用程式,Flutter 支援延遲組成部分;對於 iOS,我們一直在努力開發工具以預先編譯著色器,以消除或減少第一次運行的卡頓。我們還為 DevTools 套件添加了一些新功能,這些功能可以幫助您了解應用程式中的記憶體分配方式,以及對第三方工具擴展的支援。

此外,我們一直在著手幾個重要的潤色領域,例如改進 Web 目標的可存取性。

我們的發展不僅限於 Flutter 的核心。我們還與其他 Google 團隊合作,幫助將 Flutter 整合到我們更廣泛的開發人員堆疊中。特別是,我們繼續建立值得信賴的服務,幫助開發人員負責任地在應用程式中獲利。此版本中更新了我們的 [新廣告 SDK](https://developers.google.com/admob/flutter/quick-start),包含空安全和對適應性橫幅格式的支援。我們還引入了一個由 Google Pay 團隊合作開發的 [新的付款 Plugin](http://pub.dev/packages/pay),它讓您可以在 iOS 和 Android 上對實體商品進行付款。此外,我們更新了 [應用程式內購買 Plugin](https://pub.dev/packages/in_app_purchase),以及相應的 [Codelab](https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases)。

作為驅動 Flutter 的「秘訣」,[Dart](https://dart.dev) 也在此版本中進行了更新。Dart 2.13 擴展了對原生互操作性的支援,包括在 FFI 中支援陣列和封包結構。它還包括對類型別名的支援,這提高了可讀性,並為某些重構情境提供了一個平緩的路徑。我們繼續為更廣泛的生態系統添加整合,包括一個 Dart [GitHub Action](https://github.com/marketplace/actions/setup-dart-sdk) 和一個經過優化的 [Docker 官方映像](https://hub.docker.com/_/dart),專為雲端部署業務邏輯而設計。

超越 Google 專案

雖然 Google 仍然是 Flutter 專案的主要貢獻者,但我們很高兴看到圍繞 Flutter 的更廣泛生態系統的成長。

在最近幾個月中,Flutter 的成長表現特別突出,它被用於越來越多的平台和作業系統。在 Flutter Engage 上,我們宣布了 [豐田將把 Flutter 带入他們的下一代車輛信息娛樂系統](https://medium.com/googleplaydev/seamless-multi-platform-app-development-with-flutter-ea0e8003b0f9#f53d)。上個月,Canonical 發佈了他們的首個 [帶有整合 Flutter 支援的 Ubuntu](https://ubuntu.com/blog/ubuntu-21-04-is-here),具有 Snap 整合和對 Wayland 的支援。

兩位新合作夥伴證明了這個不斷發展的生態系統。[三星正在將 Flutter 移植到 Tizen](https://github.com/flutter-tizen/flutter-tizen), 開源儲存庫可供其他人貢獻。而 [索尼正在帶頭努力為嵌入式 Linux 提供解決方案](https://github.com/sony/flutter-embedded-linux)。

設計師也從這個專案的開源性質中受益,[Adobe 宣布了其更新的 XD to Flutter 外掛](https://medium.com/adobetech/announcing-xd-to-flutter-v2-0-82d09f3909a7)。Adobe XD 為設計師提供了一個很好的方式來實驗和迭代。現在,隨著增強的 Flutter 支援,設計師和開發人員可以在相同的資產上進行合作,讓好點子更快地投入生產。

最後,微軟繼續與我們合作;除了 Surface 團隊一直在努力使用 Flutter 建立可折疊體驗之外,本週還推出了為 Windows 10 建立的 [Flutter 對 UWP 應用程式的 Alpha 版支援](https://flutter.dev/desktop#windows-uwp)。我們很高兴看到更多利用 Flutter 中內建的平台適應來提供跨行動、桌面、Web 和其他平台的優質體驗的應用程式。

建立出色的體驗

最重要的是,我們建立 Flutter 是為了幫助開發人員建立出色的體驗。我們熱衷於這樣的想法:應用程式開發可以變得更好;我們可以透過消除傳統的障礙來讓您接觸到您的受眾,來賦予您力量。

我們喜歡看到您如何將 Flutter 運用於實際工作中。一個例子來自美國退伍軍人事務部的一個專案。下面的影片顯示了他們的 Flutter 應用程式如何幫助他們為患有創傷後壓力症候群的士兵提供康復服務。

Google I/O 上有 [關於 Flutter 的各種研討會、簡報和隨選課程](https://events.google.com/io/program/content?4=topic_flutter),我們很高興能與大家分享我們的成果。不要忘記查看我們用 Flutter 建立的有趣的 [照片亭 Web 應用程式](https://photobooth.flutter.dev),它讓您能夠與我們的 Dash 吉祥物和她的朋友們合照自拍!


在 Google I/O 2021 上宣布 Flutter 2.2 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

深入探討使用 Flutter 和 Firebase 建立 Web 應用程式

我們(Very Good Ventures 的團隊)與 Google 合作,為今年的 Google I/O 帶來了互動式體驗:一個 照片亭!您可以與知名的 Google 吉祥物合影: Flutter 的 Dash、Android Jetpack、Chrome 的 Dino 和 Firebase 的 Sparky,並使用貼紙裝飾照片,包括派對帽、披薩、時髦眼鏡等等。最後,您可以將照片分享到社交媒體,並下載它們以更新您的活動個人檔案照片!

Flutter 的 Dash、Firebase 的 Sparky、Android Jetpack 和 Chrome 的 Dino

我們使用 網頁上的 FlutterFirebase 建立了 I/O 照片亭。由於 Flutter 現在支援 Web 應用程式,我們認為這將是一個很好的方法,讓今年的虛擬 Google I/O 全球的與會者都能輕鬆地使用這個應用程式。Flutter 的 Web 支援消除了必須從應用程式商店安裝應用程式的障礙,也讓您能夠選擇在您偏愛的設備上運行它:行動裝置、桌面或平板電腦。這讓任何有瀏覽器和設備的人都能使用 I/O 照片亭,而無需下載。

儘管 I/O 照片亭被設計為 Web 體驗,但所有程式碼都是使用平台無關的架構撰寫的。當相机插件等元素的原生支援在各自的平台上可用時,同一程式碼可以在所有平台(桌面、Web 和行動裝置)上運行。

使用 Flutter 建立虛擬照片亭

為 Web 建立 Flutter 相機 Plugin

第一個挑戰是為網頁上的 Flutter 建立一個相機 Plugin。最初,我們聯繫了 Baseflow 的團隊,因為他們維護著現有的開源 Flutter 相機 Plugin。雖然 Baseflow 致力於為 iOS 和 Android 建立頂級的相機 Plugin 支援,但我們很樂意使用 聯合 Plugin 方法 並行開發 Plugin 的 Web 支援。我們盡可能地遵循官方 Plugin 介面,以便在 Plugin 準備就緒時能夠將它合併回官方 Plugin 中。

我們識別了兩個對在 Flutter 中建立 I/O 照片亭相機體驗至關重要的 API。

  1. 初始化相機: 應用程式首先需要存取您的設備相機。在桌面裝置上,這可能是網路攝影機,而在行動裝置上,我們選擇的是前置相機。我們還提供了 1080p 的預期解析度,以根據您的設備最大限度地提高相機品質。
  2. 拍攝照片: 我們使用了內建的 HtmlElementView,它使用平台視圖將原生 Web 元素渲染為 Flutter Widget。在此專案中,我們將 VideoElement 渲染為一個原生 HTML 元素,這就是您在拍攝照片之前在螢幕上看到的內容。我們使用 CanvasElement,它被渲染為另一個 HTML 元素。這使我們可以在您點擊拍攝照片按鈕時從媒體流中捕獲圖片。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Future<CameraImage> takePicture() async {
final videoWidth = videoElement.videoWidth;
final videoHeight = videoElement.videoHeight;
final canvas = html.CanvasElement(
width: videoWidth,
height: videoHeight,
);
canvas.context2D
..translate(videoWidth, 0)
..scale(-1, 1)
..drawImageScaled(videoElement, 0, 0, videoWidth, videoHeight);
final blob = await canvas.toBlob();
return CameraImage(
data: html.Url.createObjectUrl(blob),
width: videoWidth,
height: videoHeight,
);
}

相機權限

在我們讓 Flutter 相機 Plugin 在 Web 上運作之後,我們建立了一個抽象層來顯示不同的 UI,具體取決於相機權限。例如,在等待您允許或拒絕瀏覽器使用相機的權限,或者沒有可用的相機可以存取時,我們可以顯示一個說明訊息。

1
2
3
4
5
6
7
8
9
Camera(
controller: _controller,
placeholder: (_) => const SizedBox(),
preview: (context, preview) => PhotoboothPreview(
preview: preview,
onSnapPressed: _onSnapPressed,
),
error: (context, error) => PhotoboothError(error: error),
)

在此抽象層中,placeholder 返回初始 UI,因為應用程式正在等待您授予對相機的權限。preview 在您授予權限後返回 UI,並提供相機的即時視訊流。error builder 允許我們在發生錯誤時捕獲錯誤,並渲染對應的錯誤訊息。

鏡像照片

我們的下一個挑戰是鏡像照片。如果我們直接使用相機拍攝照片,您看到的將不是您在鏡子中看到的那樣。 一些設備有設定可以精確處理這一點,因此,如果您使用前置相機拍攝照片,您會在拍攝時看到鏡像版本。

在我們的第一種方法中,我們嘗試捕獲預設的相機視圖,然後在 y 軸上應用 180 度變換。這似乎有效,但後來我們遇到了 一個問題,Flutter 有時會覆蓋變換,導致視訊恢復為未鏡像的版本。

在 Flutter 團隊的幫助下,我們透過將 VideoElement 包裹在 DivElement 中並更新 VideoElement 以填充 DivElement 的寬度和高度解決了這個問題。這使我們能夠將鏡像應用到 video element 上,而不會讓 Flutter 覆蓋變換效果,因為父元素是 div。這種方法為我們提供了所需的鏡像相機視圖!

Un-mirrored view
Mirrored view

堅持嚴格的縱橫比

對於大型螢幕,強制執行 4:3 的嚴格縱橫比,對於小型螢幕,強制執行 3:4 的縱橫比比想像的要難!在整個 Web 應用程式的設計中強制執行這個比率,以及確保在您將照片分享到社交媒體時,照片看起來完美無瑕,這一點非常重要。這是一項具有挑戰性的任務,因為設備上內建相機的縱橫比差異很大。

為了強制執行嚴格的縱橫比,應用程式首先使用 JavaScript getUserMedia API 請求設備相機所能提供的最大解析度。然後,我們將此 API 饋送到 VideoElement 流中,這就是您在相機視圖中看到的內容(當然是鏡像的)。我們還應用了一個 object-fit CSS 屬性,以確保 video element 覆蓋其父容器。這使用 Flutter 中內建的 AspectRatio Widget 設定縱橫比。結果,相機不會對顯示的縱橫比做出任何假設;它始終返回支援的最大解析度,然後符合 Flutter 提供的約束(在本例中為 4:3 或 3:4)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
final orientation = MediaQuery.of(context).orientation;
final aspectRatio = orientation == Orientation.portrait
? PhotoboothAspectRatio.portrait
: PhotoboothAspectRatio.landscape;
return Scaffold(
body: _PhotoboothBackground(
aspectRatio: aspectRatio,
child: Camera(
controller: _controller,
placeholder: (_) => const SizedBox(),
preview: (context, preview) => PhotoboothPreview(
preview: preview,
onSnapPressed: () => _onSnapPressed(
aspectRatio: aspectRatio,
),
),
error: (context, error) => PhotoboothError(error: error),
),
),
);

使用拖放添加朋友和貼紙

I/O 照片亭體驗中的一個重要部分是與您最喜歡的 Google 朋友合影並添加道具。您可以將朋友和道具拖放到照片中,以及調整它們的大小和旋轉它們,直到得到一張您喜歡的圖片。您會注意到,在將朋友添加到螢幕時,您可以拖動和調整它們的大小。朋友們也有動畫 - 精靈表來實現這個效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
for (final character in state.characters)
DraggableResizable(
canTransform: character.id == state.selectedAssetId,
onUpdate: (update) {
context.read<PhotoboothBloc>().add(
PhotoCharacterDragged(
character: character,
update: update,
),
);
},
child: _AnimatedCharacter(name: character.asset.name),
),

為了調整物件的大小,我們建立了一個可拖動、可調整大小的 Widget,它可以包裝在任何 Flutter Widget 周圍,在本例中是朋友和道具。此 Widget 使用 LayoutBuilder 來根據視窗的約束處理 Widget 的縮放。在內部,我們使用 GestureDetectors 來接入 onScaleStartonScaleUpdateonScaleEnd。這些回調提供關於手勢的詳細資訊,這些資訊需要反映您對朋友和道具所做的更改。

Transform Widget 和 4D 矩陣變換根據您使用多個 GestureDetectors 報告的各種手勢,處理朋友和道具的縮放和旋轉。

1
2
3
4
5
6
7
Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..scale(scale)
..rotateZ(angle),
child: _DraggablePoint(...),
)

最後,我們建立了一個單獨的套件來確定您的設備是否支援觸控輸入。可拖動、可調整大小的 Widget 根據觸控功能進行適應。在支援觸控輸入的設備上,可調整大小的錨點和旋轉圖示不可見,因為您可以捏合和拖動來直接操作圖片,而在沒有觸控輸入的設備(例如您的桌面設備)上,會添加錨點和旋轉圖示以適應點擊和拖動。

優先考慮網頁上的 Flutter

使用 Flutter 進行以 Web 為中心的開發

這是我們使用 Flutter 建立的第一個 Web 專案,它與行動應用程式具有不同的特性。

我們需要確保應用程式對任何設備上的任何瀏覽器都 響應式和自適應。也就是說,我們必須確保 I/O 照片亭會根據瀏覽器大小進行縮放,並且能夠處理行動裝置和 Web 輸入。我們通過以下幾種方式實現了這一點:

  • 響應式調整大小: 您應該能夠將瀏覽器調整到所需的尺寸,並且 UI 應相應地調整。如果您的瀏覽器視窗處於縱向模式,則相機將從具有 4:3 縱橫比的橫向視圖翻轉到具有 3:4 縱橫比的縱向視圖。
  • 響應式設計: 桌面瀏覽器的設計將 Dash、Android Jetpack、Dino 和 Sparky 顯示在右側,而行動裝置則顯示在頂部。桌面設計還使用相機右側的抽屜,而行動裝置則使用 BottomSheet 類別。
  • 自適應輸入: 如果您從桌面設備存取 I/O 照片亭,則滑鼠點擊被視為輸入,如果您使用的是平板電腦或手機,則使用觸控輸入。這在調整貼紙大小並將它們放置在照片中時尤其重要。行動裝置支援捏合和拖動,而桌面裝置支援點擊和拖動。

可擴展架構

我們還將建立可擴展行動應用程式的方法應用於此應用程式。我們從一個堅實的基礎開始 I/O 照片亭,包括健全的空安全、國際化,以及從第一次提交開始的 100% 單元測試和 Widget 測試覆蓋率。我們使用 flutter_bloc 進行狀態管理,因為它允許輕鬆地測試業務邏輯並觀察應用程式中的所有狀態更改。這對開發人員日誌和追蹤性特別有用,因為我們可以精確地看到從一個狀態到另一個狀態的變化,並更快地隔離問題。

我們還實作了功能驅動的單一儲存庫結構。例如,貼紙、分享和實時相機預覽是在它們自己的資料夾中實作的,每個資料夾包含其各自的 UI 組件和業務邏輯。它們與外部相依項整合,例如相機 Plugin,這些相依項存在於 packages 子目錄中。這種架構使我們的團隊能夠並行處理多個功能,而不會中斷他人的工作,最大限度地減少了合併衝突,並使我們能夠有效地重複使用程式碼。例如,UI 組件函式庫是一個單獨的套件,稱為 photobooth_ui,相機 Plugin 也是單獨的。

透過將組件分成獨立的套件,我們可以提取和開源不與此特定專案相關聯的單獨組件。即使是 UI 組件函式庫套件也可以開源給 Flutter 社群,類似於 MaterialCupertino 組件函式庫。

Firebase + Flutter = 完美的搭配

Firebase 驗證、儲存、託管等等

照片亭利用 Firebase 生態系統進行各種後端整合。firebase_auth 包 支援在應用程式啟動時匿名登入使用者。每個工作階段都使用 Firebase Auth 建立一個具有唯一 ID 的匿名使用者。

這在您到達分享頁面時會發揮作用。您可以下載照片以儲存為您的個人檔案照片,或者您可以直接分享到社交媒體。如果您下載了照片,它將儲存在您的設備上。如果您分享了照片,我們會使用 firebase_storage 包 將照片儲存在 Firebase 中,以便我們以後能夠檢索它,為社交媒體貼文填充內容。

我們在 Firebase 儲存桶上定義了 Firebase 安全規則,以使照片在建立後不可變。這可以防止其他使用者修改或刪除此儲存桶中的照片。此外,我們使用 Google Cloud 提供的 Object Lifecycle Management,定義一個規則,刪除所有 30 天前的物件,但您可以按照應用程式中概述的說明請求更快地刪除您的照片。

此應用程式還使用 Firebase 托管 來快速且安全地託管 Web 應用程式。action-hosting-deploy GitHub Action 允許我們根據目標分支自動將部署到 Firebase 托管。當我們將更改合併到 main 分支時,action 會觸發一個工作流程,將應用程式的開發風味構建並部署到 Firebase 托管。同樣,當我們將更改合併到 release 分支時,action 會觸發生產部署。GitHub Action 與 Firebase 托管的組合使我們的團隊能夠快速迭代,並始終擁有最新構建的預覽。

最後,我們使用 Firebase Performance Monitoring 監控關鍵的 Web 效能指標。

使用 Cloud Functions 與社交媒體互動

在生成您的社交媒體貼文之前,我們首先要確保照片看起來完美無瑕。最終的圖片包括一個紀念 I/O 照片亭的精美框架,並裁剪為 4:3 或 3:4 的縱橫比,使其在社交媒體貼文中看起來很棒。

我們使用 OffscreenCanvas API 或 CanvasElement 作為 polyfill 來組合原始照片和包含您的朋友和道具的圖層,並生成一張您可以下載的單張圖片。image_compositor 包 處理此處理步驟。

然後,我們利用 Firebase 強大的 Cloud Functions 來幫助將照片分享到社交媒體。當您點擊分享按鈕時,您將被帶到所選平台上的新標籤頁,其中包含預先填寫的貼文。貼文包含一個 URL,該 URL 會重新導向到我們編寫的 Cloud Function。當瀏覽器分析 URL 時,它會檢測 Cloud Function 生成的動態元資訊。此資訊允許瀏覽器在您的社交媒體貼文中顯示照片的精美預覽圖片,以及指向分享頁面的連結,您的關注者可以在其中查看照片並導航回到 I/O 照片亭應用程式以拍攝自己的照片。

1
2
3
4
5
6
7
8
function renderSharePage(imageFileName: string, baseUrl: string): string {
const context = Object.assign({}, BaseHTMLContext, {
appUrl: baseUrl,
shareUrl: `${baseUrl}/share/${imageFileName}`,
shareImageUrl: bucketPathForFile(`${UPLOAD_PATH}/${imageFileName}`),
});
return renderTemplate(shareTmpl, context);
}

最終的產品看起來像是這樣:

有關如何在 Flutter 專案中使用 Firebase 的更多資訊,請查看此 codelab

最終產品

這個專案很好地體現了以 Web 為中心的應用程式建立方法。我們驚訝地發現,與我們使用 Flutter 建立行動應用程式的體驗相比,建立此 Web 應用程式的流程是如此相似。我們必須考慮視窗大小、響應式、觸控與滑鼠輸入、圖片加載時間、瀏覽器相容性以及建立 Web 應用程式時需要考慮的所有其他事项。但是,我們仍然使用相同的模式、架構和編碼標準編寫 Flutter 程式碼。在為 Web 建立應用程式時,我們感到賓至如歸。Flutter 套件的工具和不斷發展的生態系統,包括 Firebase 工具套件,讓 I/O 照片亭成為可能。

Very Good Ventures 團隊,他們參與了 I/O 照片亭的開發

我們已將所有程式碼開源。在 GitHub 上查看 photo_booth 專案,並在 Facebook 和 Twitter 上使用 #IOPhotoBooth 向我們展示您的照片!


製作過程:I/O 照片亭 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

哪些因素影響了使用者採用 Flutter 的決定?— 2021 年第一季使用者調查結果

Flutter 團隊在此分享本季使用者調查的結果!本季,我們在 3 月 5 日至 11 日期間,歷時 7 天,收集了超過 8,000 份回覆。這個季度的調查計畫旨在以結構化的形式聽取您的意見,以便 Flutter 團隊能夠專注於對使用者最重要的方面。先前調查的結果也發佈在 Medium 上。

使用者滿意度

在本季度的調查中,8,652 位受訪者中有 92% 表示對 Flutter 感到滿意(55% 非常滿意,37% 有點滿意),與上一季度的結果類似。

本季值得注意的是,89% 的受訪者也對 Dart 語言感到滿意,創下歷史新高。這個消息讓團隊非常鼓舞,因為這個百分比在 2019 年起步時只有 80%。Dart 團隊做了很多工作來改善開發人員使用 Dart 語言的體驗,以達成此滿意度,包括 健全的空安全。我們很高興分享這個調查結果,並感謝那些承認該語言獨特優勢的人。

對 Dart 感到滿意的使用者比例從 2019 年第三季度的 80% 增加到 2021 年第一季度的 89%,增長了 9%。

哪些因素影響了使用者採用 Flutter 的決定?

Flutter 團隊希望了解不同的因素如何影響使用者為新專案採用 Flutter 的決定。目標是找到團隊應該投入的領域,以減輕使用者的疑慮,並讓使用者感到滿意。此外,透過分享結果,我們希望您也能使用這些資訊來尋找貢獻 Flutter 社群的方式,或在您的組織或社群中宣傳 Flutter。

由於這次調查的目標是現有的 Flutter 使用者,因此我們詢問了使用者最近評估 Flutter 用於其下一個新專案的經驗。我們了解到 75% 的受訪者在過去 3 個月內評估了 Flutter 與其他技術的比較,其中 67% 是出於商業原因,其次是學習(17%)和興趣(14%)。

首先,我們詢問什麼因素讓使用者傾向於採用 Flutter。如以下圖表所示,使用者傾向於採用 Flutter 的主要原因是 Flutter 支援以下功能,按重要性排序:

  1. 單一程式碼庫。
  2. 現成的 UI Widget。
  3. 熱重載。
讓開發人員傾向於為其下一個專案採用 Flutter 的因素

接下來,我們詢問什麼因素讓使用者傾向於不採用 Flutter。使用者最擔心的因素是以下這些,按重要性排序:

  1. Google 對 Flutter 的承諾。
  2. Flutter 對於他們正在構建的應用程式規模的成熟度。
  3. Flutter 生態系統中提供的套件和插件。
讓開發人員不願為其下一個專案採用 Flutter 的因素

從這些結果中,團隊了解到使用者擔心 Flutter 是否會長期存在。這是一個合理的擔憂,因為您將您的職業或應用程式與我們的框架綁定在一起。因此,我們想再次提到內部採用的規模。在 Flutter Engage 上,我們分享了 Google 有超過 30 個團隊正在使用 Flutter 構建任務關鍵的應用程式。這些團隊包括 Google Pay、Google Ads、Nest Hub 和 Stadia,這些團隊擁有數千名開發人員致力於 Flutter 開發。今年,Flutter 將再次在 Google I/O 上佔據重要地位。請留意我們最新的公告,並從 5 月 5 日開始註冊 I/O 網站 上列出的 Flutter 會議。

我們還想指出,Flutter 的成長不僅僅是因為 Google 的支援——Google 外部的貢獻者比 Google 內部的貢獻者更多。全球充滿活力的開源開發人員社群正在為我們共同的成功做出貢獻!看看其他大型和小型貢獻者,例如 Toyota 或 Ubuntu。

接下來的擔憂是 Flutter 的成熟度,包括它周圍的生態系統。我們正在投資開發套件和插件生態系統,並致力於核心框架的穩定性和品質。隨著 Flutter 2 的發布和不斷增長的生態系統支援它,我們看到人們在這裡的觀點正在改善。現在網頁支援已穩定,桌面支援也處於 Beta 階段,我們在即將到來的版本中主要將會以完善框架和提升您使用 Flutter 可以達到的生產力為主題。同時,您可以查看 Flutter 網站的 展示區,了解 BMW、eBay、Nubank、騰訊、Square 和 Sonos 等主要品牌如何使用 Flutter 構建應用程式。

我們還收集了數千條關於各種主題的原始評論,以回應開放式問題。我們至少舉辦了三個不同的研討會,Flutter 子團隊的工程師在這些研討會上聚在一起閱讀和消化關於各種主題的評論,包括生態系統、開發人員工具等等。研討會期間產生的想法將作為團隊未來幾個季度目標的輸入。

Flutter 團隊用於根據調查中的評論生成和組織有關開發人員工具的想法的線上便利貼

社群貢獻者也可以做一些事情。我們從使用者評論中了解到,許多 Flutter 開發人員仍然希望擁有品質更高的套件,並提供更好的維護,儘管他們承認 Flutter 的生態系統隨著時間推移而成熟。有很多關於多媒體套件(如音訊和影片播放器)和藍牙套件的提及,這些套件需要更好的支援。我們歡迎您貢獻這些領域,擴展覆蓋範圍,例如向現有套件提交 PR,因為 Flutter 團隊努力提供高品質的 第一方套件

基於雲端的服務和產品

Flutter 團隊知道一些 Flutter 使用者對雲端服務有興趣,但團隊並不清楚使用者在尋找哪種類型的雲端解決方案。感謝調查,我們了解到 40% 的開發人員使用基於雲端的服務,27% 的開發人員計畫在他們的 Flutter 專案中使用基於雲端的服務。

對於那些已經使用基於雲端的服務的人來說,最受歡迎的雲端解決方案是 Firebase (82%),其次是 Google Cloud Platform (GCP) (34%) 和 Amazon Web Services (AWS) (25%)。

使用者表示,他們選擇 Firebase 和 GCP 的原因是它們易於與 Flutter 一起使用。許多選擇 AWS 和 Azure 的使用者表示,這是因為他們已經熟悉這些平台。

Flutter 團隊與 Firebase 和 GCP 密切合作。我們將繼續支援 FlutterFire Plugin,團隊也與 GCP 團隊合作,使其更容易與 Flutter 一起使用。

接下來要做什麼?

Flutter UXR 團隊將每季度進行調查。您可以在 flutter.dev 上,Flutter IDE Plugin 中,或 Twitter 上 @FlutterDev 找到公告。您也可以註冊即將到來的 UX 研究,參與其他研究。請繼續分享您的想法,因為團隊正在尋找重要問題的答案。

再次感謝所有參與此次調查並提供寶貴意見的人。我們閱讀了每則意見回饋,並將其銘記於心。我們的目標是打造一款您喜愛的產品,我們感謝您的時間和努力幫助我們!


哪些因素影響了使用者採用 Flutter 的決定?— 2021 年第一季使用者調查結果 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

宣布 XD to Flutter v2.0!

* 為設計師提供通往生產 Flutter 程式碼的快速路徑 *

XD to Flutter

Flutter 是 Google 的開源 UI 工具包,可使用單一程式碼庫為行動、桌面、網頁和嵌入式設備構建精美的應用程式。在過去的幾年中,它已成為想要為多個平台構建應用程式的開發人員的領先選擇;但設計師需要一個視覺工具來製作原型和建立 Flutter UI,而不是手工編寫 Dart 原始碼。這就是 XD to Flutter 誕生的原因!

從插件的第一次預覽發布至今已將近一年,我們一直都在不斷改進和完善它,進行了一些小更新,在去年夏天發布了重大的 v1.0 版本,現在又發布了 v2.0 版本,以配合 Flutter 2 的發布!

等等,XD to Flutter 是什麼?

這個名字可能已經洩露了答案,但 XD to Flutter 插件是一個功能強大、易於使用的工具,可以將您在 Adobe XD 中設計的精美作品匯出為乾淨、功能性的 Flutter 程式碼。您可以從設計中複製特定視覺元素的程式碼,匯出可重複使用的 Widget,甚至可以匯出完整的視圖。

這意味著,使用 XD to Flutter 插件,您可以透過點擊按鈕,讓您的設計在幾乎任何設備上運行。它不會為您編寫整個應用程式,但會為您提供一個良好的開端。

XD to Flutter 由 gskinner 與 Adobe 合作開發,並作為 Adobe XD 本身的插件發布,因此您可以將它用於您正在建立的任何現有 Adobe XD 設計。

太棒了!那麼有什麼新功能?

XD to Flutter 的初始版本對輸出設計中的所有不同視覺元素提供了良好的支援 - 向量圖形、圖片、富文字、背景模糊、混合模式、陰影等 - 但結果可能是靜態且缺乏彈性的。

雖然它對於擷取圖示或文字樣式很方便,但我們希望它能做更多事情!XD 使設計師能夠使用響應式佈局、可捲軸區域、堆疊和網格等工具來建立動態 UI;我們希望插件支援所有這些功能,而 v2.0 版本讓我們取得了很大進展。

響應式調整大小

XD to Flutter 支援 XD 的響應式佈局功能,讓您可以在其封閉的父元素中「固定」元素,並精確控制它們的調整大小方式。

Adobe XD 中的響應式設計
Flutter 中的響應式調整大小

這是透過在開源的 adobe_xd 套件中使用自訂的 Pinned 佈局 Widget 來實現的,開發人員可以直接在他們的專案中利用它。

Pinned Widget 程式碼範例

堆疊和捲軸組

「堆疊」和捲軸組提供了在 Adobe XD 中以動態方式佈置螢幕上內容的新方法。XD 中的堆疊讓您可以在水平或垂直列表中排列許多不同的元素,元素之間的間距各不相同;它們更類似於 Flutter 中的 Flex Widget,而不是它們的同名 Stack Widget。

捲軸組預測性地讓您可以在設計中直接定義一個區域,以垂直或水平方式捲軸更大的內容組。

XD to Flutter v2.0 支援這兩種功能,將它們轉換為常見的 Flutter Widget(ColumnRowSingleChildScrollView)。您甚至可以將堆疊放在捲軸組中,輕鬆建立一個捲軸項目列表。

XD 中的堆疊和捲軸組(左)以及 Flutter 中的堆疊和捲軸組(右)

填補和背景元素

另一個新功能是背景元素,讓您可以將視覺元素指定為組的背景。這可以與填補配對,將背景的邊緣與內容分開。

Flutter 匯出使用 Stack Widget 將背景元素放置在內容後面,內容被放置在 Padding Widget 中。

XD 中的填補和背景(左)以及 Flutter 中的填補和背景(右)

Flutter 2 和空安全性

上面描述的佈局功能使 UI 具有更強的響應性,這與 Flutter 2 對桌面和網頁等外觀形式的支援增強相得益彰。

Flutter 2 還引入了健全的空安全性 - 一個語言功能,可以幫助開發人員在空值問題引發應用程式問題之前捕獲它們。XD to Flutter v2.0 包括一個新的設定「匯出空安全程式碼」,確保生成的程式碼是面向未來的。

「匯出空安全程式碼」設定和輸出

聽起來很棒!我該如何開始?

無論您是使用它來複製複雜漸變的程式碼,還是匯出完全響應式、參數化、互動式 Widget,加入已經使用 XD to Flutter 插件的數千名創意專業人士都很簡單。

您可以透過從 Adobe XD 的「插件」選單中選擇「瀏覽插件…」並搜尋「Flutter」(奇怪的是,搜尋「XD to Flutter」不起作用)來安裝它,或者只訪問 adobe.com/go/xd_to_flutter

安裝好之後,從插件面板中打開 XD to Flutter 面板,然後點擊「需要幫助?」連結以查看 插件文件

Flutter 2 是框架向前邁出的令人興奮的一步,重點是構建可以在幾乎任何地方運行的精美應用程式。在 gskinner,我們很高興能與 Adobe 和 Google 合作,確保 XD to Flutter 繼續使將迷人的設計忠實地轉換為工作產品的過程變得更加容易。

敬請期待插件的更多令人興奮的更新!


宣布 XD to Flutter v2.0! 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

從同一個程式碼庫發佈到網路和行動裝置

Flutter’s web support is now available in stable

我們對 Flutter 的願景是成為一個可移植的 UI 框架,用於在任何平台上建立精美的應用程式體驗。今天,作為 Flutter 2 的一部分,我們宣佈 Flutter 的網路支援已達到穩定里程碑。

第一個 Flutter 版本支援 iOS 和 Android,並且已被用於將超過 150,000 個應用程式帶到行動應用商店。現在,新增網路支援意味著這些相同的應用程式可以接觸到更廣泛的觀眾,並打開新的方式在網路上建立互動式體驗。

在此網路支援的初始版本中,我們專注於三個應用程式場景:

  • 漸進式網路應用程式 (PWA) 結合了網路的覆蓋範圍和桌面應用程式功能。
  • 單頁應用程式 (SPA) 僅載入一次,並與網際網路服務傳輸資料。
  • 將現有的 Flutter 行動應用程式擴展到網路,使兩者共用程式碼。

本文描述了我們到目前為止所建立的內容,並探討了一些例子,說明您如何在自己的應用程式中利用 Flutter 的網路支援。

iRobot Education developed the iRobot Coding app using Flutter to offer their learn-to code experience to everyone anywhere by making it available on the web.
iRobot 教育 使用 Flutter 開發了 iRobot 程式設計應用程式,透過在網路上提供他們的程式設計學習體驗,讓世界各地的人都能體驗到。

我們邁向網路的旅程

當今的網路平台比以往都更加豐富,擁有 硬體加速的 2D 和 3D 圖形、[離線和安裝支援] (https://web.dev/progressive-web-apps/),以及 存取底層作業系統和硬體。網路允許 廣泛的 陣列 框架 建立在這個底層平台之上,為開發人員提供很大的彈性,讓他們可以選擇如何為網路建立應用程式。

由於 Flutter 是用 Dart 編寫的,而 Dart 是一種提供 JavaScript 編譯的語言,因此探索網路作為目標是自然而然的一步。這也符合我們提供一個可移植框架的願景,讓您可以在任何想要繪製像素的地方建立精美的 UI。

我們的方法是建立一個一致的工具組,可以在所有平台上運行(而不是擁有兩個具有微妙行為偏差的獨立框架),以確保您的程式碼在運行時不會出現意外情況。

Flutter web support’s architecture diagram

在架構層面上,Flutter 是一个 多層系統,具有:

  • 框架,提供對通用慣用語的抽象,例如 Widget、動畫和手勢。
  • 引擎,使用它公開的系統 API 渲染到目標設備。

框架本身是用 Dart 編寫的,大約 700,000 行核心 Flutter 框架程式碼在所有平台上都相同:行動裝置、桌面,以及現在的網路。您的程式碼也是如此;我們使用 Dart 開發編譯器 ( dartdevc ) 或 Dart 部署編譯器 ( dart2js ) 將您的程式碼編譯成 JavaScript,然後可以將其託管在伺服器上。

有了 Dart 將 Flutter 框架(以及您的應用程式程式碼)編譯成 JavaScript 的能力,我們支援網路的工作涉及用對映到網路平台 API 的程式碼替換行動應用程式使用的低階 C++ 渲染引擎。Flutter 並不是簡單地將其 Widget 轉換成 HTML 對應物。相反,Flutter 的網路引擎提供兩種渲染器的選擇:一個針對大小和廣泛相容性進行優化的 HTML 渲染器,以及一個使用 WebAssembly 和 WebGL 將 Skia 繪製命令渲染到瀏覽器畫布的 CanvasKit 渲染器。

我們對 Flutter 的目標是提供一種新的方式來定位網路平台,建立在現有基礎的基礎上,並提供新的見解來改善每個人的網路體驗。

發佈生產品質的穩定版本

自從一年前我們的 網路支援的測試版發佈 後,我們學到了很多關於早期使用者如何使用它的知識,並且與一些客戶合作,他們現在已將其 Flutter 網路應用程式發佈到生產環境。

在此期間,我們進行了主要的架構改進,並新增了功能來擴展和優化 Flutter 的網路支援,重點關注四個領域:效能特定於網路的功能桌面尺寸外掛

Flutter web support’s stable release features

效能

自我們早期版本以來,效能是最大的改進領域。在開發過程中,我們更好地了解了網路平台上可用的各種渲染技術的效能和正確性特徵。

我們最初開始使用基於 HTML、DOM 的模型。在此模型中,Flutter 的網路引擎將每個產生的 Flutter 場景轉換成 HTML、CSS 或 Canvas,並將一個圖形渲染到頁面上,形成一個 HTML 元素樹。儘管 HTML 渲染器提供了與各種瀏覽器最大的相容性,並且程式碼大小更小,但 HTML 渲染器的重新繪製效能不太適合更注重圖形的應用程式,例如 Rive,一個使用 Flutter 建立的協作工具,用於建立動態圖形。

Rive, a tool for creating custom animations, rebuilt their app using Flutter on the web and it is now available in beta.
Rive,一個用於建立自訂動畫的工具,使用 Flutter 在網路上重建了他們的應用程式,現在可在測試版中使用。

為了處理高效能地渲染密集圖形所需的保真度,我們開始嘗試使用 CanvasKit,它可以使用 WebAssemblyWebGL 在瀏覽器中渲染 Skia 繪製命令。我們發現 CanvasKit 可以提供卓越的效能、保真度和正確性,實現了 Felix Blaschke(Flutter 社群中一位才華橫溢的成員)在 這個演示 中體現的圖形處理能力。

Flutter Plasma, a demo created by Felix Blaschke, running on Safari, Firefox, Edge and Chrome.
Flutter Plasma,由 Felix Blaschke 建立的演示,在 Safari、Firefox、Edge 和 Chrome 上運行。

每個渲染器在不同的場景中都具有優勢,因此 Flutter 支援兩種渲染模式:

  • HTML 渲染器: 使用 HTML 元素、CSS、Canvas 元素和 SVG 元素的組合。此渲染器具有較小的下載大小。
  • CanvasKit 渲染器: 此渲染器與 Flutter 行動裝置和桌面完全一致,具有更高的 Widget 密度,但下載大小增加了約 2MB。

為了針對每個設備的特點優化您的 Flutter 網路應用程式,渲染模式預設設置為自動。這意味著您的應用程式在行動瀏覽器上使用 HTML 渲染器,在桌面瀏覽器上使用 CanvasKit 渲染器。

您也可以使用 –web-renderer html 或 –web-renderer canvaskit 明確選擇您的應用程式使用的渲染器。如需更多資訊,請參閱 網路渲染器

特定於網路的功能

在瀏覽器中運行的 Flutter 應用程式應感覺像一個網路應用程式。因此,我們在 Flutter 中新增了一些功能,可以幫助您充分利用網路。

網路具有許多優勢,尤其是其全球覆蓋範圍。將現有的 Flutter 應用程式帶到網路上的眾多原因之一是接觸到應用程式商店之外的使用者。為此,我們新增了對 自訂 URL 策略 的支援,以確保您的使用者只需點擊一個 URL 即可在任何地方訪問到您的應用程式。使用此功能,您可以控制地址欄中顯示的 URL,以及您的應用程式在網路上的路由。

Flutter Plasma demo’s showroom page is an example of the url_strategy plugin, based on Flutter’s custom URL strategies, in action.
Flutter Plasma 演示 的展示間頁面是基於 Flutter 的自訂 URL 策略的 [url_strategy Plugin](https://pub.dev/packages/url_strategy) 的實際應用範例。

超連結也是使用者在網路上導航方式的關鍵。url_launcher 套件中的一個新的連結 Widget 使使用者能夠深度連結到您的應用程式中的錨點或外部網站。您可以在相關的 Widget 上使用連結,包括按鈕、內嵌文字、圖片,並指定連結是在同一個標籤頁中打開還是新標籤頁中打開。

任何應用程式的另一個重要部分是文字渲染。為文字開發佈局系統是支援 Flutter 在網路上的最大挑戰之一。由於網路缺乏直接文字佈局 API,因此 Flutter 必須透過觸發 layout()段落 進行各種測量。這些測量可能會非常昂貴,因此新的 基於畫布的文字測量 為純文字和富文字添加了支援。現在,Flutter 可以高效地在網路上進行詳細的測量,從而實現一些功能,例如在選定的文字上準確地繪製突出顯示框。

與文字互動與能夠快速準確地渲染文字一樣重要。現在可以使用 SelectableText 和 EditableText Widget 選擇、複製和貼上文字。此外,表單文字欄位支援 自動填充,允許瀏覽器儲存資料並處理未來自動填充的案例。

Flutter 2 特别适合实现渐进式网络应用程序 (PWA)。透過 Chrome 的 Project Fugu 的努力,PWA 可以很好地填補行動裝置和網路應用程式之間的差距,以安全可靠的方式。

Invoice Ninja, an invoice management app, launched the PWA app using the same codebase as their existing Flutter mobile apps.
Invoice Ninja,一個發票管理應用程式,使用與其現有的 Flutter 行動應用程式相同的程式碼庫發佈了 PWA 應用程式。

當您建立 Flutter 網路應用程式時,我們會包含一個 PWA 網路清單檔案,以及用於設置服務工作者的程式碼。清單檔案 提供有關應用程式如何運行的中繼資料,包括圖示和應用程式標題等資訊。服務工作者 可以啟用資源的快取和離線運行應用程式。當您在瀏覽器中作為 PWA 運行 Flutter 應用程式時,您將看到有機會將其安裝到您的設備上,無論是作為行動裝置應用程式還是桌面應用程式。

對桌面尺寸的支援

我們希望讓 Flutter 網路體驗感覺正確,無論您的瀏覽器視窗的形狀和大小如何。在行動瀏覽器上,Flutter 應用程式已經對從行動應用程式支援繼承的手勢和捲軸物理特性提供了出色的支援。但是,桌面瀏覽器提供了不同的 UI 功能,因此我們對 Flutter 進行了相應的更新。

例如,人們期望桌面上的內容顯示可以使用滑鼠或鍵盤控制的捲軸條。因此,新的 可自訂的互動式捲軸條 支援 主題、軌道,以及透過拖動滑塊進行捲軸的功能。PrimaryScrollController 已擴展,因此您可以使用 鍵盤快捷鍵進行捲軸,而無需連接自己的捲軸視圖。

Property management solution for Zurich Insurance, built by Spica Technologies, is a great example of the business apps Flutter’s web support can enable on desktop browsers.
由 [Spica Technologies](https://spicatech.co.uk/) 為 [Zurich Insurance](https://www.zurich.com/) 建立的房地產管理解決方案是 Flutter 的網路支援可以讓桌面瀏覽器啟用商業應用程式的絕佳範例。

我們還提高了 預設內容密度,因為滑鼠指標比觸控設備支援更高的密度。我們在框架中新增了一組 系統滑鼠游標,以支援所有平台。

最後,為了支援 所有 使用者,Flutter 的網路語義功能已擴展以支援 Windows、macOS 和 ChromeOS 的無障礙功能。在網路上,會並發產生一個名為 SemanticsNode 樹的第二個 DOM 樹,與 RenderObject DOM 樹並行。SemanticsNode 樹將標誌、動作、標籤和其他語義屬性轉換成 ARIA 屬性。現在,您可以使用 NarratorVoiceOverTalkBackChromeVox 螢幕閱讀器來導航 Flutter 網路應用程式。

外掛生態系統

最後,網路支援已新增到一些最常用的外掛中,使您能夠將現有的 Flutter 應用程式帶到網路上。Flutter 外掛 允許您的程式碼與您正在運行的平台的原生函式庫互動。當您在網路上運行 Flutter 應用程式時,您可以透過外掛存取現有的 JavaScript 函式庫。

自測試版發佈以來,並在社群的幫助下,新增了對以下外掛的支援:

展望未來

幾年前,不可能以可接受的品質和效能來提供 Flutter 在網路上運行。但是,新網路技術的引入和平台的持續進步使我們能夠充分發揮底層設備的潛力。有了對網路的支援,Flutter 涵蓋了網際網路上的所有設備,並在所有現代瀏覽器和設備上提供一致的體驗。

此版本的許多定義來自早期網路採用者的回饋,以及社群提交的議題。由衷地感謝你們!展望未來,我們的首要目標是解決您的回饋並快速解決問題,讓您能夠專注於在 所有 目標平台上發佈高品質的 Flutter 應用程式。

Moi Mobiili, a modern Mobile Virtual Network Operator, recently launched their web app using Flutter.
Moi Mobiili,一個現代行動虛擬網路營運商,最近使用 Flutter 發佈了他們的網路應用程式。

效能可能會一直是投資領域。我們的目標是減少程式碼大小,提高每秒畫面數 (fps)。今天,每個 Flutter 網路應用程式都會下載它需要的引擎程式碼。我們正在探索快取部分邏輯的可能性,以減少啟動時間和下載大小。我們最近在 Flutter 圖庫演示應用程式中做了些工作,透過延遲載入函式庫來減少程式碼大小,並計畫很快分享我們的經驗。

我們還將在接下來的幾個月中繼續改進一些領域:

Simplebet used Flutter’s web support to build highly interactive embeddable NFL & NBA betting experiences within Fanduel’s existing suite of mobile apps.
Simplebet 使用 Flutter 的網路支援在 Fanduel 現有的行動應用程式套件中建立高度互動式的可嵌入 NFL 和 NBA 投注體驗。

開始使用 Flutter 在網路上運行

有了 Dart 的可移植性、網路平台的强大功能以及 Flutter 框架的靈活性,您現在可以從同一個程式碼庫為 iOS、Android 和瀏覽器建立應用程式。

對於那些已經擁有現有 Flutter 網路應用程式的使用者,您現在可以在 stable channel 中建立您的應用程式。如果您是 Flutter 網路應用程式開發的新手,請查看 flutter.dev/web、我們的 入門 codelab 以及 Flutter Engage 的 網路分組會議。在您建立網路應用程式時,請務必在 GitHub 上提交任何議題。

我們迫不及待想要看到您使用 Flutter 的新網路支援建立什麼!


Flutter 網路支援達到穩定里程碑 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 2 的新功能

Flutter 網頁和空安全移至穩定版,Flutter 桌面移至 Beta 版,還有更多新功能!

今天,我們很高興宣佈 Flutter 2 的發佈。自 Flutter 1.0 發佈以來已經過去了兩年多,但在這短短的時間裡,我們已經解決了 24,541 個議題,並合併了來自 765 位貢獻者的 17,039 個 PR。僅從 9 月份發佈的 Flutter 1.22 版本至今,我們已經解決了 5807 個議題,並合併了來自 298 位貢獻者的 4091 個 PR。特別感謝我們自願的貢獻者,他們慷慨地貢獻自己的閒暇時間來改進 Flutter 專案。Flutter 2 版本中排名前三的自願貢獻者是 xu-baolin,他提交了 46 個 PR,a14n,他提交了 32 個 PR,專注於將 Flutter 帶入空安全,以及 hamdikahloun,他提交了 20 個 PR,改進了許多 Flutter Plugin。但不僅僅是程式碼作者為 Flutter 專案做出了貢獻;一批優秀的自願 PR 審查者也負責審查了 1525 個 PR,包括 hamdikahloun(再次!)、CareFYazeedAlKhalaf(他只有 16 歲!)。Flutter 確實是一個社群努力的結果,沒有議題提出者、PR 貢獻者和程式碼審查者,我們不可能達到 2.0 版。此版本是獻給你們所有人的。

在 Flutter 2 版本中,發生了很多令人興奮的事情。有關 Flutter 2 和 Dart 2.12 的所有新功能的概述,以及我們的客戶和合作夥伴如何使用 Flutter 2,請參閱 宣佈 Flutter 2。有關 Dart 2.12 的詳細資訊,請參閱 宣佈 Dart 2.12。有關如何充分利用 Flutter 網頁(現在已建議用於生產環境)的資訊,請參閱 Flutter 網頁支援達到穩定里程碑

此外,若要查看 Flutter 2 本身的新功能,請繼續閱讀!

網頁

從今天起,Flutter 的網頁支援已從 Beta 版轉移到穩定頻道。有了這個初始的穩定版本,Flutter 以對網頁平台的支援將程式碼的可重複使用性推向了另一個層級。因此,現在當你在穩定版中建立 Flutter 應用程式時,網頁只是你應用程式的另一個設備目標。

[Moi Mobiili](https://www.moi.fi/),一家現代化虛擬行動網路營運商,努力透過數位化實現運營卓越,選擇使用 Flutter 建立他們的 Mun Moi 帳戶管理應用程式,並最近推出了他們的網頁應用程式。

透過利用網頁平台的許多優勢,Flutter 建立了用於建立豐富互動式網頁應用的基礎。我們主要關注效能和渲染保真度的改進。除了我們的 HTML 渲染器之外,我們還加入了新的 CanvasKit 基礎渲染器。我們還加入了一些特定於網頁的功能,例如 Link Widget,以確保在瀏覽器中運行的應用程式感覺像一個網頁應用程式。

Flutter 的網頁支援部落格文章 中找到有關此穩定版本的更多詳細資訊。

空安全

空安全是 Dart 語言的一個重要新增功能,它透過區分可空類型和不可空類型來進一步強化類型系統。這使開發人員能夠防止空錯誤崩潰,這是應用程式崩潰的常見原因。透過將空檢查整合到類型系統中,這些錯誤可以在開發過程中被捕獲,從而防止在生產環境中出現崩潰。空安全在 Flutter 2(包含 Dart 2.12)中得到完全支援。有關更多詳細資訊,請參閱 Dart 2.12 部落格文章

pub.dev 套件儲存庫中已經發佈了 超過 1,000 個空安全的套件,包括 DartFlutterFirebaseMaterial 團隊的數百個套件。如果您是套件作者,請查看 遷移指南,並考慮今天就進行遷移。

桌面

在此版本中,我們很高興地宣佈 Flutter 的桌面支援在穩定頻道中以早期版本標誌的形式提供。這意味著我們已經準備好讓您嘗試將其作為 Flutter 應用程式的部署目標:您可以將其視為「beta 快照」,預覽今年晚些時候發佈的最終穩定版本。

為了使 Flutter 桌面達到這種程度的品質,從確保文字編輯在每個支援的平台上都能像原生體驗一樣運作開始,包括基礎功能,例如 文字選取中心點 以及能夠在 處理鍵盤事件後停止事件傳播。在滑鼠輸入方面,使用高精度點選裝置進行拖動現在會立即開始,而不是等待處理觸控輸入所需的延遲。此外,為 MaterialCupertino 設計語言的 TextField 和 TextFormField Widget 添加了一個內建的內容選單。最後,為 ReorderableListView Widget 添加了抓取控制柄

ReorderableListView 現在具有抓取控制柄,方便使用滑鼠進行拖放。

ReorderableListView 始終擅長移動項目,作為開發人員,您幾乎不需要付出任何努力,但它需要使用者使用長按來啟動拖動。這在行動設備上是有道理的,但很少有桌面使用者會想到用滑鼠長按一個項目來移動它,因此此版本包含一個適用於滑鼠或觸控輸入的抓取控制柄。另一個針對平台特有功能的改進是 更新的捲軸條,它會在桌面外觀中正確顯示。

此版本包含更新的 Scrollbar Widget,在桌面環境中效果很好。

Scrollbar Widget 已更新,以提供桌面預期的互動式功能,包括拖動滑塊、點擊軌道以向上和向下翻頁以及在滑鼠懸停在捲軸條的任何部分時顯示軌道。此外,由於可以使用 新的 ScrollbarTheme 類別 來設定 Scrollbar 的主題,因此您可以對其進行樣式設定以符合應用程式的樣式和感覺。

為了提供其他特定於桌面的功能,此版本還為 Flutter 應用程式啟用了命令列引數處理,因此可以使用簡單的操作(例如在 Windows 檔案總管中雙擊資料檔案)在應用程式中打開檔案。我們還努力為 WindowsmacOS 都實現更流暢的調整大小操作,並為國際使用者啟用 IME(輸入法編輯器)。

Flutter 桌面現在支援直觀的 IME 輸入。

此外,我們還提供了 有關如何開始為您的桌面應用程式準備部署到適當的作業系統特定商店的更新文件。請試用它們,如果我們遺漏了任何內容,請提供回饋。

在嘗試 Flutter 桌面的 Beta 版時,您可以透過切換到 Beta 版頻道(預期如此)並根據 flutter.dev 上的說明 為您要鎖定的平台設定配置標誌來存取它。此外,我們還在穩定頻道上提供了 Beta 版的快照。如果您使用 flutter config 來啟用其中一個桌面配置設定(例如,enable-macos-desktop),那麼您可以嘗試桌面支援的 Beta 版功能,而無需經歷移動到 Beta 版頻道和下載 Flutter SDK 的最新 Beta 版、建立工具等的冗長過程。這非常適合試用或將桌面支援用作簡單的「Flutter 模擬器」。

但是,如果您選擇停留在穩定頻道以存取桌面 Beta 版,則您獲得新功能或錯誤修復的速度將不如切換到 Beta 版或開發頻道快。因此,如果您積極鎖定 Windows、macOS 或 Linux,我們建議您切換到一個提供更新更快的頻道。

隨著我們第一個完整的生產級品質的 Flutter 桌面版本即將推出,我們知道我們還有更多工作要做,包括支援與原生頂級選單整合、讓文字編輯更像個別平台的體驗、可存取性支援,以及一般的錯誤修復和效能改進。如果您認為在桌面移至生產級品質之前還有其他事情需要做,請務必 提供您的回饋

平台適應性應用程式:Flutter Folio 樣本

現在 Flutter 支援三個生產應用程式平台(Android、iOS 和網頁)以及三個 Beta 版平台(Windows、macOS 和 Linux),一個自然的問題出現了:如何編寫一個能夠很好地適應多種不同外觀尺寸(小、中和大螢幕)、不同輸入模式(觸控、鍵盤和滑鼠)和不同慣例(行動、網頁和桌面)的應用程式?為了回答這個問題,我們為自己和所有地方的 Flutter 開發人員委托了 Flutter Folio 剪貼簿應用程式。

Folio 旨在成為一個簡單的應用程式範例,您希望能夠從單個程式碼庫中在多個平台上良好運行。而「良好」是指,它在小、中和大螢幕上看起來都不錯,它利用了觸控、鍵盤和滑鼠輸入,並且適用於平台的慣例(例如,在網頁上使用連結,在桌面上使用選單)。我們將這種應用程式稱為「平台適應性應用程式」,因為它能夠很好地適應其執行的任何平台。

如果您想了解如何製作自己的平台適應性應用程式,可以查看 Folio 的原始碼。在未來,您會發現更多探討這個主題的文件和 Codelab。在此期間,請查看 Aloïs Deniel 關於這個主題的出色部落格文章和影片

Google 行動廣告移至 Beta 版

除了 Flutter 桌面移至 Beta 版之外,今天我們還很高興地宣佈 Google 行動廣告 SDK for Flutter 的公開 Beta 版。這是一個全新的 Plugin,除了現有的覆蓋格式(覆蓋橫幅、插頁式和獎勵型影片廣告)之外,它還提供了內嵌橫幅和原生廣告。這個 Plugin 統一了對 Ad Manager 和 Admob 的支援,因此無論您是什麽規模的發佈商,這個 Plugin 都可以針對您的場景進行調整。

我們已經與一些早期客戶在一個私人 Beta 程式中試用了這個 Plugin,並且他們中的許多人已成功使用這些新的格式推出了他們的應用程式。例如,Sua Musica(拉丁美洲最大的獨立音樂人音樂平台,擁有超過 15,000 名經過驗證的音樂人和 1,000 萬個 MAU)使用 Google 行動廣告 SDK for Flutter Plugin 推出了他們的全新 Flutter 應用程式。他們在展示次數上看到了 350% 的增長,點擊率增加了 43%,eCPM 增加了 13%。

這個 Plugin 現在已可供您使用。作為 Flutter Engage 的一部分,Andrew Brogdon 和 Zoey Fan 介紹了一個關於「使用 Flutter 變現應用程式」的議程(在 Flutter Engage 上提供),他們在這個議程中討論了使用 Flutter 建立的應用程式的變現策略,以及如何在 Flutter 應用程式中載入廣告。此外,我們在 flutter.dev 上建立了一個新的 廣告 頁面,您可以在其中找到所有有用的資源,例如 Plugin 實作指南內嵌橫幅和原生廣告 Codelab,以及 覆蓋橫幅、插頁式和獎勵型影片廣告 Codelab。請務必查看它們!

新的 iOS 功能

僅僅因為我們正在繼續提高對其他平台的支援品質,並不意味著我們忘記了 iOS。事實上,此版本帶來了 178 個合併的 PR,這些 PR 與 iOS 相關,包括 23495,它為 iOS 帶來了狀態還原,67781,它滿足了長期以來的一個需求,即可以直接從命令列構建 IPA,而無需打開 Xcode,以及 69809,它更新了 CocoaPods 版本以匹配最新的工具。此外,還為 Cupertino 設計語言實作添加了一些 iOS Widget。

新的 CupertinoSearchTextField 提供了 iOS 搜尋欄 UI。

CupertinoFormSectionCupertinoFormRowCupertinoTextFormFieldRow Widget 使得使用 iOS 的分段視覺美學更容易製作經驗證的表單欄位。

除了針對 iOS 的功能工作之外,我們還在繼續 研究針對 iOS 和 Flutter(在著色器和動畫方面)的效能改進。iOS 仍然是 Flutter 的主要平台,我們將繼續努力為其帶來重要的新功能和效能改進。

新的 Widget:Autocomplete 和 ScaffoldMessenger

此版本的 Flutter 附帶了兩個額外的新 Widget,AutocompleteCore 和 ScaffoldMessenger。AutocompleteCore 代表了將自動完成功能加入到 Flutter 應用程式中所需的最低限度功能。

自動完成是 Flutter 中經常被要求的功能,因此此版本開始提供此功能。您現在可以使用它,但如果您對完整功能的設計感到好奇,請查看 自動完成設計文件

同樣地,ScaffoldMessenger 的建立是为了解决許多與 SnackBar 相關的問題,包括能够轻松地在響應 AppBar 動作時创建 SnackBar、创建 SnackBar 以在 Scaffold 轉換之間持久存在,以及能够在异步動作完成時显示 SnackBar,即使使用者已經导航到具有不同 Scaffold 的頁面。

所有這些好東西都可以透過幾行程式碼來實現,從現在開始,您應該使用這些程式碼來顯示 SnackBar:

1
2
final messenger = ScaffoldMessenger.of(context);
messenger.showSnackBar(SnackBar(content: Text('I can fly.')));

正如您可能想像到的,它不仅仅是这些;有关详细信息,请查看Kate Lovett 关于 ScaffoldMessenger 的出色视频

使用 Add-to-App 進行多個 Flutter 實例

我們從與許多 Flutter 開發人員的交談中了解到,許多開發人員没有機會從头开始建立新的应用程序,但他们可以透過將 Flutter 加入到現有的 iOS 和 Android 應用程式中來利用 Flutter。這個功能稱為 Add-to-App,是在保留現有的原生程式碼庫的同時,在兩個行動平台上重複使用 Flutter 程式碼的絕佳方法。但是,對於使用這種方式的開發人員,我們有時會听到,他們不清楚如何超越將第一個螢幕整合到 Flutter 中。交織 Flutter 和原生螢幕會使导航狀態难以维护,而在視圖级别整合多個 Flutter 會占用大量的記憶體。

過去,額外的 Flutter 實例與第一個實例具有相同的記憶體成本。在 Flutter 2 中,我們將建立額外 Flutter 引擎的靜態記憶體成本降低了約 99%,降至每個實例約 180kB。

啟用此功能的新 API 在 Beta 版頻道中提供預覽,並在 flutter.dev 上有文件,以及 一組演示這種新模式的範例專案。有了這個變化,我們現在不再猶豫推薦在您的原生應用程式中建立多個 Flutter 引擎實例。

Flutter Fix

每當任何框架成熟並吸引越來越多的使用者,隨著時間推移,他們的程式碼庫也越來越大,人們往往會避免對框架 API 進行任何更改,以免破壞越來越多的程式碼行。隨著全球超過 500,000 名 Flutter 開發人員在越來越多平台上使用 Flutter,Flutter 2 正在迅速邁入這個行列。但是,為了使我們能夠隨著時間的推移繼續改進 Flutter,我們希望能夠對 API 進行重大更改。問題是,如何在不破壞開發人員的情況下繼續改進 Flutter API?

我們的答案是 Flutter Fix

Flutter Fix 是多種事物的組合。首先,dart CLI 工具中有一個新的命令列選項,稱為 dart fix,它知道在哪裡尋找已棄用 API 列表以及如何使用這些 API 更新程式碼。其次,它是可用修復本身的列表,從版本 2 開始與 Flutter SDK 捆綁在一起。最後,它是一組更新的 Flutter 擴展,用於 VS Code、IntelliJ 和 Android Studio IDE,這些擴展知道如何將相同的可用修復列表作為快速修復顯示,並帶有小的燈泡,有助於您用滑鼠點擊來更改程式碼。

舉例來說,假設您的應用程式中有以下程式碼行:

使用已棄用參數建立 Flutter Widget

因為此建構函數的參數已棄用,因此應該替換為以下內容:

使用已棄用參數被替換的 Flutter Widget 建立

即使您熟悉 Flutter 中的許多已棄用 API,但要更改的程式碼越多,您要應用所有修復程式就越困难,犯错的可能性也越大;人类不擅长这种重复性任务。但電腦很擅长;透過執行以下命令,您可以查看我們知道如何在整個專案中進行的所有修復:

1
$ dart fix --dry-run

如果您想批量應用它們,您可以輕鬆地做到:

1
$ dart fix --apply

或者,如果您想在您喜歡的 IDE 中互動式地應用這些修復程式,您也可以做到。

雖然我們已經將舊的 API 標記為已棄用多年,但現在我們 制定了關於何時真正移除已棄用 API 的政策,Flutter 2 是我們第一次這樣做。即使我們还没有將所有已弃用的API作為數據捕获以供 Flutter Fix 使用,我們也將繼續從之前已弃用的 API 中添加更多 API,並在未來的重大更改中繼續这样做。我們的目標是尽力使 Flutter 的 API 达到最佳状态,同时在进行更改时也保持您的代码最新。

Flutter DevTools

為了明确 DevTools 应该是一个用于调试 Flutter 应用程序的工具,我们将其重命名为在调试 Flutter 应用程序时称为 Flutter DevTools。此外,我们做了很多工作,使其达到足以与 Flutter 2 相匹配的生产级品质。

一项新的功能可以帮助您在启动 DevTools 之前找到问题,即 Android Studio、IntelliJ 或 Visual Studio Code 可以注意到常见的异常,并建议将其在 DevTools 中打开以帮助您调试它。例如,以下显示您的应用程序中出现了溢出异常,这将在 Visual Studio Code 中提供一个选项,用于在 DevTools 中调试该问题。

Flutter IDE 扩展会注意到您的应用程序何时抛出布局溢出异常

按下那个按钮会直接带您到 DevTools 中的 Flutter Inspector,指向导致问题的 Widget,这样您就可以对其进行修复。我们今天只针对布局溢出异常这样做,但我们的计划是将这种处理方式扩展到所有常见的异常,而 DevTools 可以作为解决这些异常的方案。

在 DevTools 运行后,选项卡上的新错误徽章可以帮助您在应用程序中找出具体问题。

DevTools 中的红点可以帮助您关注应用程序中出现错误的部分

DevTools 中的另一个新功能是能够轻松地查看比显示尺寸更高的分辨率的图像,这有助于跟踪应用程序的大小和内存使用情况。若要启用此功能,请在 Flutter Inspector 中启用「反转超尺寸图像」。

启用「反转超尺寸图像」选项以突出显示比实际需要更大的图像

现在,当您显示的分辨率明显大于其显示尺寸的图像时,它将上下颠倒显示,以便您在应用程序中轻松找到它。

「反转超尺寸图像」选项在行动中

此外,应广大用户的要求,除了在 Flutter Inspector 的布局资源管理器中显示有关灵活布局的详细信息外,我们还添加了显示固定布局的功能,使您能够调试各种类型的布局。

新的布局资源管理器显示了固定布局和灵活布局的布局详细信息

而且这还不是全部。以下只是 Flutter DevTools 2 中一些新功能的摘要:

  • 在 Flutter 畫面圖表中添加了平均 FPS 資訊和可用性改進
  • 在網路分析工具中使用紅色錯誤標籤來突出顯示失敗的網路請求
  • 新的記憶體檢視圖表更快、更小、更容易使用,包括一個新的懸停卡來描述特定時間的活動
  • 在記錄選項卡中添加了搜尋和過濾
  • 追蹤 DevTools 啟動之前的記錄,以便您在啟動 DevTools 時查看完整的記錄歷史記錄
  • 將「效能」檢視重新命名為「CPU 分析工具」,使功能更明確
  • 在 CPU 分析工具火焰圖表中添加了時間網格
  • 將「時間軸」檢視重新命名為「效能」,使功能更明確

而且這 仍然 不是全部。為了獲得完整的功能变更集,我推荐以下公告:

Android Studio/IntelliJ 擴展

針對 IntelliJ IDE 系列的 Flutter Plugin 也為 Flutter 2 添加了一些新功能。首先,有一個新的專案嚮導,它與 IntelliJ 中的新嚮導樣式相匹配。

此外,如果您在 Linux 上使用 IntelliJ 或 Android Studio 對 從 Snap 商店安裝的 Flutter SDK 進行編程,則 Flutter snap 路徑已添加到已知 SDK 路徑列表中。這使得 Snap 的 Flutter 使用者可以更輕鬆地在設定中配置 Flutter SDK。感謝 MarcusTomlinson@ 的貢獻!

Linux 上的 Android Studio 更易於使用透過 Snap 安裝的 Flutter SDK

您可以在最近更新的公告中閱讀更多關於這些好東西的內容:

  • IntelliJ Plugin M51
  • IntelliJ Plugin M52
  • IntelliJ Plugin M53
  • IntelliJ Plugin M54

Visual Studio Code 擴展

Visual Studio Code 的 Flutter 擴展也針對 Flutter 2 進行了改進,從許多測試增強功能開始,包括僅重新執行失敗測試的功能。

經過兩年的開發,Dart 的 LSP(語言伺服器協定)支援現在正在推出,作為獲得 Dart 分析器以整合到 Visual Studio Code 的 Flutter 擴展中的預設方式。LSP 支援為 Flutter 開發帶來了許多改進,包括能夠在當前的 Dart 檔案中應用特定類型的所有修復程式,以及讓程式碼完成生成完整的函數調用,包括括號和必需參數。

而且 LSP 支援不僅僅適用於 Dart;它也支援在 pubspec.yamlanalysis_options.yaml 檔案中的程式碼完成。

這些只是 Visual Studio Code 的 Flutter 擴展最近獲得的一些更新。您可以在這些公告中閱讀完整的列表:

  • Visual Studio Code Plugin v3.16
  • Visual Studio Code Plugin v3.17
  • Visual Studio Code Plugin v3.18
  • Visual Studio Code Plugin v3.19
  • Visual Studio Code Plugin v3.20

DartPad 更新為支援 Flutter 2

這個工具更新列表沒有提及 DartPad 就不完整,DartPad 已更新為支援 Flutter 2。

DartPad 已更新為支援 Flutter 2

現在

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 在 2020 年上半年的效能更新

作者:Yuqian LiShams Zakhour

速度是 Flutter 的關鍵支柱。本文重點介紹 Flutter 社群成員在 2020 年上半年實施的效能改進。

如果您在 2020 年 6 月之後幫助過效能改進,我們將在未來的文章中涵蓋這些內容。我們希望與您分享這些內容,希望 Flutter 社群受到鼓舞,一起參與改進 Flutter 效能的努力!

量化改善

貢獻者: alexmarkovsstricklmkustermannaskeksa-googlermacnak-googlemralephcrelier

[應用程式大小] 透過字體子集處理,Gallery 應用程式縮減了 100KB 的大小

貢獻者: dnfieldjonahwilliamszandersojmagmanblasten

  • PR 1482849737498425022451808
  • Flutter Gallery 應用程式縮减了 100KB 的大小 (大小縮減)
  • 修復了「搖樹 Material 圖示 16311」,「將 hb-subset 作為引擎組建的一部分進行組建並上傳到雲端儲存 43642」,「在 flutter_tools 中使用 font-subset 並搖樹圖示字體 43644」,「為所有平台連接字體子集處理 49730“)。

[速度、記憶體] dart2js 工具的運行速度提升了 9 倍,記憶體減少了 99% 以上

貢獻者: rmacnak-googlea-siva

[速度] 從 OpenGL 切換到 Metal,iOS 平均渲染速度提升了 50%

貢獻者: chinmaygardednfieldjason-simmonscbrackenamirhliyuqian

[速度] 由於著色器編譯,最差畫面渲染時間提升了 2 到 5 倍

貢獻者: liyuqianjonahwilliamschinmaygardeiskakaushikzandersosfshaza2filiphacoutts

  • PR 173005385917601178615874356638443012142
  • Android 的 flutter_gallery__transition_perf 最差畫面渲染時間 worst_frame_rasterizer_time_millis 提升了 2.25 倍 (從 90ms 到 40ms)
  • iOS 的 flutter_gallery_ios32__transition_perf 最差畫面渲染時間 worst_frame_rasterizer_time_millis 提升了 5 倍 (從 300ms 到 60ms)
  • 一些實際應用程式的速度提升了 3.75 倍 (從 229ms 到 61ms)
  • 修復了「基於 SkSL 的著色器預熱 53607」、「三次貝茲曲線回歸 35142」和「儲存」一些客戶。

[速度] 滑鼠點擊測試速度提升了 15.8 倍

貢獻者: dkwingsmtyjbanovgoderbauergspencergoog

  • PR 59803 59883
  • bench_mouse_region_grid_scroll 的畫面持續時間 (網頁) 提升了 15.8 倍 (從 79ms 到 5ms)。
  • 修復了「訂閱 MouseRegion 事件時效能低下 41194

[速度] 平台訊息回應處理速度提升了 13.9 倍

貢獻者: zljj0818jason-simmonsliyuqian

  • PR 1883818945,兩者都受 18808 啟發
  • 修復了「載入大型圖片時,Image.asset 會阻塞 UI 線程 58572
  • PlatformMessageResponseDartComplete 速度提升了 13.9 倍 (從 9164us 到 660us)

[速度] 使用不透明路由時,畫面構建時間提升了 20% 到 37%

貢獻者: goderbauerdnfield

  • PR 48900
  • flutter_gallery_ios32__transition_perf 的平均畫面構建時間 average_frame_build_time_millis 提升了 20% (從 7.38ms 到 6.13ms)
  • flutter_gallery_ios32__transition_perf 的第 99 個百分位數畫面構建時間 99th_percentile_frame_build_time_millis 提升了 37% (從 50.45ms 到 36.63ms)
  • 修復了「在推入覆蓋/導航器不透明內容時,優化不必要的重建 45797

[速度] 使用 ImageFiltered 而不是 BackdropFilter,模糊效果速度提升了 4.8 倍

貢獻者: flarhixieyjbanovliyuqian

[速度] 使用 Flutter 網頁捲軸大型靜態內容時,速度提升了 14 倍

貢獻者: yjbanovferhatb

  • PR 17621
  • text_canvas_cached_layout.html.layout.average 速度提升了 14.01 倍 (從 463.74ms 到 33.10ms)
  • 修復了「使用 Flutter Web 捲軸大型靜態內容時卡頓 42987」和「在 Web 上繪製畫布邊界外的文字很昂貴 48516

[速度] Flutter 引擎 Shell 初始化速度提升了 6.8 倍

貢獻者: scutlightjason-simmonsgaaclarkeliyuqian

[速度] 限制條件相同時,跳過調用構建器,速度提升了 5 倍

貢獻者: yjbanovhixie

  • PR 55414
  • 使用 Flokk 客戶端應用程式捲軸聯絡人列表時,速度提升了 5 倍(從大約 10FPS 到大約 50FPS)。
  • 修復了「LayoutBuilder 應該快取限制條件,如果沒有改變就不應該重新建立 6469

[速度] 網頁上的陰影和動畫速度提升了 2 倍

貢獻者: ferhatbmdebbaryjbanov

貢獻者: ferhatbclocksmithrami-a

[速度] 在 Fuchsia 中啟用柵格快取後,平均畫面渲染時間提升了 2.8 倍

貢獻者: drevemanliyuqianchinmaygardearbreng

  • PR 17753
  • frame_rasterizer_times_avg 速度提升了 2.8 倍(從大約 10ms 到大約 3.5ms)
  • 修復了「由於柵格快取被停用,Fuchsia 上的效能低下 54950

[速度] 透過排除無效的動畫圖片,第 90 個百分位數畫面構建時間提升了 1.85 倍

貢獻者: dnfieldliyuqiantvolkertdigiter

  • PR 5085150842
  • animated_placeholder_perf 的第 90 個百分位數畫面構建時間提升了 1.85 倍 (從 3.148ms 到 1.699ms)
  • 修復了「當長列表中的卡片內部使用列表構建器時,flutter 的畫面速率很低 (平均 20 到 35fps) 35592

[速度] Google 智能顯示器 P10 的 FPS 提升了 2 倍

貢獻者: chinmaygardednicoaracbrackenjason-simmonsasakhartrdaum

  • PR 15980
  • 透過讓嵌入器可以調整線程優先順序,速度提升了 2 倍(從 30fps 到 60fps)。
  • 修復了問題 49551

[速度] 透過增強子元素快取,ImageFilterLayer 的速度提升了 2.45 倍

貢獻者: flarliyuqian

  • PR 171755490358277
  • ImageFiltered Transform 的平均畫面渲染時間 average_frame_rasterizer_time_millis 提升了 2.45 倍 (從 18.41ms 到 7.53ms)
  • 還修復了「由於 OpacityLayer 柵格快取未命中,轉場效能略有下降 52864

[速度] 大型 dart2js 編譯速度提升了 15%

貢獻者: rmacnak-googlea-siva

[速度] 大型應用程式的 AOT 編譯時間提升了 1.8 倍

貢獻者: alexmarkovmralephsigurdmcskau-g

[速度] Dart RegExp 在 AOT 模式下的匹配速度提升了 5 到 13 倍

貢獻者: mralephrmacnak-google

[速度] Dart UTF8 解碼速度提升了 5 倍

貢獻者: askeksa-googlemkustermannrakudrama

  • 提交 cf6f89e35ca378df4afa2fd4
  • X64JIT TwoByteString 基準測試速度提升了 5.02 倍。
  • 修復了「快速路徑 Uint8List 到 _OneByteString 轉換 41703」、「直接將 UTF-8 結果寫入字串 41704

[速度] async/sync* 函數的速度提升了 35% 到 65%

貢獻者: cskau-gmkustermannmraleph

  • 提交 e29407fdca1f7ed169ca94ad
  • 在 {dart,dart-aot}-{ia32,x64,armv7hf,armv8} 上,Calls.IterableManualIterablePolymorphicManyYields 的速度提升了 35% 到 65%。
  • 修復了「改進 VM 上 sync* 程式碼的效能 37753」、「在 VM 中生成 sync-yield 函數時,評估使用 IndirectGoto 37754

[速度] 使用未裝箱的參數和欄位,時間最多減少了 31.82%

貢獻者: mkustermannmkustermann

  • 提交 9eb531b95149e076e79eb531
  • matrix_utils_transform_rect_affine 迭代時間最多減少了 31.82%。
  • 修復了「Dart VM 中的真實未裝箱欄位 40004

[速度] Dart Pointer<Int8,Int64,etc> 在 AOT 中的載入/儲存速度提升了 20% 到 25%

貢獻者: dcharkesmkustermann

  • 提交 408123
  • 在 x64 上,AOT 中的 Pointer&lt;Int8,Int64,etc&gt; 載入/儲存速度提升了 20% 到 25%。
  • 幫助「儲存和載入應該支援未裝箱的索引 (在 AOT 中) 39432

其他改進

[應用程式大小、能源、記憶體、速度] 將 A/B 測試模式加入到本機 Devicelab 執行器

貢獻者: yjbanovflarferhatbchristopherfujinoliyuqian

[應用程式大小] 修復了「常見問題解答中 iOS 應用程式大小不正確」

貢獻者: [jmagman](https://github.com/

【文章內容使用 Gemini 1.5 Pro 自動產生】

您對 Flutter 感到滿意嗎? - 2020 年第 4 季使用者調查結果

Google 的 Flutter 團隊自 2018 年以來便持續進行每季一次的調查,以收集您的意見回饋 自 2018 年以來。上一季度的調查於 2020 年 11 月 23 日發布,並持續進行了 8 天。團隊收集了 8,285 份回饋,我們想與您分享這些結果!儘管這次調查的長度只有我們平常調查的一半,但我們還是像往常一樣從您的答案中學到了很多。我們非常感謝您撥冗提供寶貴的意見回饋。

使用者滿意度

總體而言,92% 的受訪者對 Flutter 有些滿意非常滿意。我們很高興能夠持續維持高滿意度。

92% 的使用者對 Flutter 感到滿意,其中 51% 非常滿意。

從圖表中可以看出,我們也學到了以下資訊:

  • 91% 的受訪者表示 Flutter 很適合他們的專案。
  • 90% 的受訪者承诺并希望在下一个项目中使用 Flutter。
  • 58% 的受访者表示 Flutter 对其公司的成功至关重要。

這些結果表明 Flutter 繼續蓬勃發展,並成為開發者工具箱的重要組成部分。

90% 的使用者希望在下個專案中使用 Flutter。

但是,我們注意到整體滿意度自上一季調查以來略有下降,從 94% 降至 92%。為了了解為什麼您對 Flutter 的各個方面並未完全滿意,團隊仔細審閱了開放式意見回饋。感謝您的回饋,團隊意識到了一些主要問題,並將投資於高優先順序項目。例如,我們計劃 改進程式碼完成,因為我們發現這是 IDE 相關問題中最常見的挫折來源。

難點

這次,我們採用了不同的方法來了解 Flutter 的難點。我們想了解什麼阻礙了您更多地使用 Flutter。當我們詢問「如果不是因為以下原因,我會更多地使用 Flutter」,26% 的受訪者選擇了 缺乏關鍵函式庫 作為原因。作為回應,我們正與 BaseflowInvertaseCodemagic 合作,以提高我們第一方套件和外掛的品質。雖然團隊正在努力改進先前研究中識別出的關鍵函式庫,但我們也在使用標籤 would be a good package 監控問題追蹤器中的特定需求,以便任何人都可以找出生態系統中缺少什麼,並為其做出貢獻。

由於 Flutter 相容套件的數量超過 15,000 個,並且 Flutter 團隊無法擴展規模來處理可能被認為是關鍵的數十甚至數百個套件,因此我們為社群提供了一系列機制來 評分套件。我們提供這些機制,以便搜尋結果能產生高品質的結果,包括讚好、靜態分析和 Flutter Favorite 認證,該認證由一群 Flutter 社群志願者頒發。這樣做不僅鼓勵您貢獻更多套件來涵蓋關鍵方面,而且套件的品質也會隨著時間推移而提升,因為套件作者會因其工作而獲得更好的分數和認可。我們將繼續投資於這個領域,以便生態系統能夠自給自足,並持續自然地提高品質。

26% 的使用者需要更多函式庫。此結果不包括 19% 表示我目前使用 Flutter 足夠的使用者。

為了讓那些從事 Flutter 之外專案的人(19%)更容易,我們將繼續投資於 add-to-app,這有助於您將 Flutter 模組整合到現有的 Android 或 iOS 應用程式中。您可以在 GitHub 議題 72009 上追蹤相關功能的進度。

核心框架中缺少的功能 被 18% 的受訪者選中。在我們仔細查看開放式意見回饋後,發現回饋集中在 Flutter 框架中包含的功能與套件提供的功能之間的界線上。雖然有些人希望框架包含更多超出使用者介面 API 的功能是可以理解的,但我們的重點是我們最擅長的 - 提供出色的 UI 框架。但是,我們想為您提供所需的功能,因此我們與社群貢獻者合作,透過套件和外掛提供特定領域和特定平台的功能。如前所述,我們投資了工具和計畫來認可高品質的套件,並幫助您在生態系統中發現它們。我們歡迎您提供回饋意見和想法,以進一步增強我們的套件生態系統。

線上社群

在這次調查中,團隊想知道您在哪裡與其他 Flutter 開發人員交流資訊或想法。雖然 21% 的受訪者表示他們沒有參與任何線上社群,但我們發現 Stack Overflow 是 Flutter 開發人員相互聯繫的最受歡迎的社群。38% 的受訪者選擇 Stack Overflow 作為他們最活躍的線上社群。

Stack Overflow 是 38% 的受訪者的主要線上社群。此圖表省略了 21% 沒有參與任何線上社群的使用者。

受訪者最活躍的地方不同,他們對社群有用性的評分也不同。例如,我們詢問「您在多大程度上同意或不同意以下關於您在上一個問題中選擇的線上社群的陳述?」對於回應 *”當我在社群中向其他 Flutter 使用者提問時,我能夠得到答案”*,在 Stack Overflow 上活躍的 75% 受訪者同意他們在 Stack Overflow 上提問時能夠得到答案。此外,61% 主要活躍在即時通訊服務上的受訪者表示他們也得到了答案。

受訪者被要求評估他們對 *"當我問…” 的問題時,我能夠得到答案"* 這個陳述的同意程度,結果因他們活躍的社群而異。

這是我們第一次評估使用者在線上的分佈情況以及他們對各種線上社群的看法。建立一個有用的和蓬勃發展的社群對 Flutter 的成功至關重要。我們與您分享這些結果,希望幫助提供者和尋求者都能更好地利用這些線上溝通管道。Flutter 團隊將監控這些資料,以指導我們的支援和教育工作,並確保您能夠尋求幫助並保持聯繫。

Flutter 活動

每年都会由当地社区小组和 Flutter 贡献者组织许多面向 Flutter 社区的线下和线上活动,约 90% 参加活动的受访者表示他们在活动中了解了 Flutter 的新知识,并认为这些信息很有帮助。虽然这些活动是有效的学习机会,但通过我们的研究,我们现在知道大多数受访者 (61%) 在 2020 年并不知道这些活动。即使我们没有像 2019 年那样举办 Flutter Interact 这样的大型活动来宣传这些活动,但这个百分比仍然高于我们的预期。因此,在计划 2021 年 3 月 3 日的 Flutter Engage 活动 时,我们将与区域 Google 团队合作,帮助宣传这些活动。我们也正在与当地 Flutter 小组密切合作,以确保我们的活动内容能够传达给更多 Flutter 社区成员。每个人都欢迎参加这个免费的线上活动。

61% 的在 2020 年没有参加任何活动 (线上和线下) 的使用者不知道有这些活動。
85% 或以上的使用者從各種 Flutter 活動中學到了新東西。

接下來會發生什麼事?

下一項調查將於 2 月底左右在 flutter.devFlutteDev (和 Flutter IDE Plugin 中宣布。您也可以透過 註冊 來參與其他研究,以參與即將到來的 UX 研究。

請繼續分享您的想法,因為團隊正在尋找重要問題的答案。

再次感謝所有參與本次調查並提供宝貴意見回饋的人。感謝您的時間和努力!

Flutter Engage 期待與您相見!


您對 Flutter 感到滿意嗎? - 2020 年第 4 季使用者調查結果 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。