【文章翻譯】Announcing Dart 3

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

宣布 Dart 3

來自 Google I/O 2023 的問候。今天,我們將從山景城現場宣布 Dart 3——迄今為止最大的 Dart 版本!Dart 3 包含三個主要進展。首先,我們完成了通往 100% 聲稱空安全性的旅程。其次,我們為記錄、模式和類修飾符添加了主要的新語言功能。第三,我們正在預覽未來,在未來我們將透過 Wasm 編譯為 Web 提供原生程式碼,從而擴展我們的平台支援。讓我們深入了解細節。

100% 聲稱空安全性

在過去的四年中,我們將 Dart 演變為一種快速、可移植且現代的語言。現在,有了 Dart 3,它成為了 100% 聲稱空安全的語言!正如我們之前所 討論過的那樣,我們認為沒有其他程式設計語言曾經為現有的語言添加過聲稱空安全性。所以,這是一段漫長的旅程。

有了 Dart 中的 100% 空安全性,我們擁有一個 聲稱 的類型系統。您可以相信,如果類型表示值不為 null,那麼它永遠不會為 null。這避免了某些類型的編碼錯誤,例如空指標異常。它還允許我們的編譯器和運行時以在沒有空安全性時無法實現的方式優化程式碼。這個設計選擇涉及一個權衡。儘管遷移變得有點困難,但我們相信我們為 Dart 做出了正確的選擇。

遷移到 Dart 3

在實現聲稱空安全性方面,Dart 社群的不懈支援至關重要:pub.dev 上排名前 1000 的套件中有 99% 支援空安全性!

基於此,我們預計絕大多數已遷移到空安全性的套件和應用程式都可以在 Dart 3 中正常運行。在極少數情況下,Dart 3 中的少量相關清除可能會影響某些程式碼。一些遺留核心函式庫 API 已被移除(#34233#49529),並且一些工具已調整(#50707)。如果您在遷移到使用 Dart 3 SDK 時遇到任何問題,請參閱 Dart 3 遷移指南。除此之外,我們希望您能享受新的合理化核心函式庫和工具。

主要語言功能 - 記錄、模式和類修飾符

Dart 3 不僅僅是關於更改現有語言。它還包括添加重要的新功能和能力!這些包括記錄、模式和類修飾符。

使用記錄構建結構化資料

傳統上,Dart 函數只能返回單個值。因此,需要返回多個值的函數必須將這些值打包到其他資料類型中,例如映射或列表,或者定義可以保存這些值的新的類別。使用未類型化的資料結構會削弱類型安全性。必須定義新的類別僅用於攜帶資料,這在編碼過程中會增加摩擦。您已經很清楚地告訴我們:對多個返回值的語言請求是我們 排名第四 的問題。

使用記錄,您可以使用乾淨利落的語法構建結構化資料。考慮這個函數。它讀取 JSON blob 的名稱和年齡,並將它們都返回到一個記錄中:

1
2
3
(String, int) userInfo(Map<String, dynamic> json) {
return (json['name'] as String, json['height'] as int);
}

這對所有 Dart 開發人員來說應該很熟悉。記錄看起來像列表常量,例如 ['Michael', 'Product Manager' ],但使用括号而不是方括号。在 Dart 中,記錄是一個通用功能。它們可以用於函數返回值以外的其他用途。您也可以將它們存儲在變數中,將它們放入列表中,將它們用作映射中的鍵,或建立包含其他記錄的記錄。您可以添加未命名的欄位,就像我們在之前的示例中所做的那樣,以及命名的欄位,例如 (42, description: 'Meaning of life')

記錄是值類型,沒有身份。這使得我們的編譯器可以在某些情況下完全擦除記錄物件。記錄還帶有自動定義的 == 運算符和 hashCode 函數。記錄文件 具有更多詳細信息。

使用模式和模式匹配處理結構化資料

記錄簡化了您構建結構化資料的方式。這不會取代使用類別來構建更正式的類型層次結構。它只提供另一個選項。無論哪種情況,您可能都希望將這些結構化資料分解成其個別元素以進行處理。這就是模式匹配發揮作用的地方。

考慮一種基本的模式形式。以下記錄模式將記錄分解成兩個新的變數 nameheight。這些變數之後可以像任何其他變數一樣使用,例如在呼叫 print 時:

1
2
var (String name, int height) = userInfo({'name': 'Michael', 'height': 180});
print('User $name is $height cm tall.');

列表和映射也存在類似的模式。對於所有這些模式,您可以使用下劃線模式來跳過個別元素:

1
var (String name, _) = userInfo(...);

模式在 switch 語句中使用時效果顯著。Dart 從一開始就對 switch 提供了有限的支援。在 Dart 3 中,我們擴展了 switch 語句的功能和表現力。我們現在在這些情況下支援模式匹配。我們已經不需要在每個 case 的末尾添加 break。我們還支援邏輯運算符來組合 case。以下示例展示了一個乾淨利落的 switch 語句,它解析字元碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
switch (charCode) {
case slash when nextCharCode == slash:
skipComment();

case slash || star || plus || minus:
operator(charCode);

case >= digit0 && <= digit9:
number();

default:
invalid();
}

當您需要為每個 case 使用一個或多個語句時,switch 語句提供了很好的幫助。在某些情況下,您只想做的是計算一個值。對於這種情況,我們提供了一個非常簡潔的 switch 表達式。這類似於 switch 語句,但使用不同的語法,該語法針對表達式進行了微調。以下示例函數返回一個 switch 表達式的值,以計算當前日期的星期幾描述:

1
2
3
4
5
6
String describeDate(DateTime dt) => 
switch (dt.weekday) {
1 => 'Feeling the Monday blues?',
6 || 7 => 'Enjoy the weekend!',
_ => 'Hang in there.'
};

模式的一個強大功能是能夠檢查「窮舉性」。此功能確保 switch 處理所有可能的情況。在前面的示例中,我們正在處理 weekday 的所有可能值,weekday 是一個 int。我們透過組合針對特定值 1、6 或 7 的匹配語句,然後使用預設情況 _ 來處理剩餘情況,來窮舉所有可能的值。若要啟用對使用者定義的資料層次結構(例如類別層次結構)的這種檢查,請在類別層次結構頂部使用新的 sealed 修飾符,如以下示例所示:

1
2
3
4
5
6
7
sealed class Animal { ... }
class Cow extends Animal { ... }
class Sheep extends Animal { ... }
class Pig extends Animal { ... }

String whatDoesItSay(Animal a) =>
switch (a) { Cow c => '$c says moo', Sheep s => '$s says baa' };

這將返回以下錯誤,提醒我們漏掉了對最後一個可能的子類型 Pig 的處理:

1
2
line 6 • The type 'Animal' is not exhaustively matched by the switch cases
since it doesn't match 'Pig()'.

最後,if 語句也可以使用模式。在下面的示例中,我們正在使用 if-case 匹配一個映射模式來分解 JSON 映射。在其中,我們根據常量值(字串,例如 'name''Michael')和類型測試模式 int h 進行匹配,以讀取 JSON 值。如果模式匹配失敗,Dart 將執行 else 語句。

1
2
3
4
5
6
7
8
final json = {'name': 'Michael', 'height': 180};

// Find Michael's height.
if (json case {'name': 'Michael', 'height': int h}) {
print('Michael is $h cm tall.');
} else {
print('Error: json contains no height info for Michael!');
}

這僅觸及了您可以使用模式完成的所有事情。我們相信它們將在所有 Dart 程式碼中變得普遍。若要進一步了解,請查看 模式文件模式程式碼實驗室

使用類修飾符為類別提供細粒度的存取控制

第三個 Dart 3 語言功能是類修飾符。與我們期望每個 Dart 開發人員使用的記錄和模式不同,這更像是一個強大的使用者功能。它滿足了編寫大型 API 表面或構建企業級應用程式的 Dart 開發人員的需求。

類修飾符使 API 作者能夠僅支援特定功能集。不過,預設值保持不變。我們希望 Dart 保持簡單易懂。因此,和以前一樣,常規類別可以 構造擴展實作,如下面的示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Vehicle {
String make; String model;
void moveForward(int meters) { ... }
}

// Construct.
var myCar = Vehicle(make: 'Ford', model: 'T',);

// Extend.
class Car extends Vehicle {
int passengers;
}

// Implement.
class MockVehicle implements Vehicle {
@override void moveForward ...
}

類修飾符支援對此添加限制。考慮一些示例用例:

  • 使用介面類別,您可以為其他人定義一個要實作的合約。介面類別不能被擴展。
  • 使用基類別,您可以確保您類別的所有子類型都繼承自它,而不是實作其介面。這確保私有方法在所有實例上都可用。
  • 使用 final 類別,您可以關閉類型層次結構,防止在您自己的函式庫之外建立任何子類別。作為一個示例優點,這允許 API 擁有者添加新的成員,而不會冒著對 API 使用者造成重大變更的風險。

有關詳細信息,請參閱新的 類修飾符文件

未來展望

Dart 3 不僅僅是您今天可以使用的功能方面的一個重大進步。我們還將預覽一下下一步。

Dart 語言

記錄、模式和類修飾符是十分重要的新功能,因此,它們的設計部分可能存在可以改進的地方。我們將繼續監控 您的回饋,並查看是否需要在 Dart 3 後的次要版本中進行更新。

我們還正在考慮一些更小、更增量式的功能,這些功能完全不可破壞,並且專注於提高開發人員的生產力,而無需遷移成本。我們正在探索的兩個示例是 內聯類別,用於以零成本的「包裝器」包裝現有類型,以及 主建構函數;此功能引入了定義包含少數欄位和主建構函數的類別的更簡潔的語法。

我們之前討論過宏(也稱為 元程式設計)。我們特別關注這一點,以實現對 JSON(和類似資料)的更好的反序列化,以及啟用資料類別。考慮到元程式設計的規模和固有的風險,我們正在採取非常徹底的方法,因此我們沒有任何明確的時間表可以分享,即使是最終確定設計決定的時間表。

原生互操作

行動裝置和桌面的應用程式通常依賴於原生平台提供的許多 API,無論是通知、支付還是獲取手機的位置。傳統上,在 Flutter 中,這些 API 是透過構建外掛來存取的,這需要同時編寫 API 的 Dart 程式碼和大量平台特定程式碼以提供實作。

我們已經支援與編譯成 C 函式庫的程式碼進行互操作,可以使用 dart:ffi。我們目前正在努力擴展此支援,以支援 Android 上的 Java 和 Kotlin 互操作 以及 iOS/macOS 上的 Objective C 和 Swift 互操作。若要了解 Android 互操作的簡介,請查看新的 Google I/O 23 Android 互操作性影片

編譯成 WebAssembly - 使用原生程式碼定位 Web

WebAssembly(簡稱為 Wasm)作為一種平台中立的二進制指令格式,在 所有現代瀏覽器 中日益成熟。Flutter 架構已經使用 Wasm 一段時間了。這是我們將以 C++ 編寫的 SKIA 圖形渲染引擎透過 Wasm 編譯的模組傳遞到瀏覽器的方式。我們一直對使用 Wasm 部署 Dart 程式碼很感興趣,但我們一直受阻。Dart 與許多其他面向物件語言一樣,使用垃圾回收。在過去的一年中,我們已與 Wasm 生態系統中的多個團隊合作,為 WebAssembly 標準添加新的 WasmGC 功能。這現在在 Chromium 和 Firefox 瀏覽器中接近穩定狀態。

我們在將 Dart 編譯成 Wasm 模組方面的工作具有兩個針對 Web 應用程式的目標:

  • 載入時間:我們希望我們能夠使用瀏覽器載入速度更快的 Wasm 傳遞部署有效載荷,從而縮短到達使用者可以與 Web 應用程式互動的點所需的時間。
  • 效能:由 JavaScript 驅動的 Web 應用程式需要即時編譯才能實現良好的效能。Wasm 模組是更低階的,更接近機器碼,因此我們認為它們可以透過更少的卡頓和更一致的畫面速率提供更高的效能。
  • 語義一致性:Dart 對於我們支援的平台之間的高度一致性感到自豪。但是,在 Web 上,有一些例外。例如,Dart Web 目前在 數字的表示方式 方面有所不同。有了 Wasm 模組,我們將能夠將 Web 視為一個「原生」平台,其語義類似於其他原生目標。

我們很興奮地宣布今天首次預覽將 Dart 編譯成 Wasm!我們最初的重點是 Flutter Web 支援。這還處於早期階段,我們還有很多工作要做,但我們 邀請您進行嘗試,看看您是否像我們一樣興奮。

結語

感謝您耐心閱讀到結尾。我們希望這篇文章讓您對 Dart 3 感到興奮,Dart 3 目前已在獨立的 Dart SDKFlutter 3.10 SDK 中提供。

我們已使用聲稱空安全性、核心函式庫和工具清理對 Dart 語言進行了重大改進。有一些主要的新語言功能,使 Dart 透過記錄和模式變得更具表現力和簡潔性。對於大型 API 表面,類修飾符啟用了詳細的控制。我們還包括對 WebAssembly 的支援預覽。

有了所有這些功能,我們認為 Dart 3 展示了我們的長期願景:為在任何平台上構建快速應用程式構建最具生產力的程式設計語言。我們希望您也這麼認為!


宣布 Dart 3 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

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

【文章翻譯】Wonderous nominated for Webby Award

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

Wonderous 榮獲 Webby 獎提名

Wonderous 在最佳使用者介面類別中獲得 Webby 獎提名。

您可以在 Webby 獎網站 上為 Wonderous 投票。

我們在 8 月份與 gSkinner 團隊合作推出 Wonderous ——一個展示 Flutter 優勢的行動應用程式。自推出以來,已有超過 3 萬名使用者安裝了 Wonderous。使用者在 App Store 上給予它 5 星評分。

Wonderous 在第 27 屆年度 Webby 獎中獲得了應用程式、dApps 和軟體類別的最佳使用者介面提名。紐約時報將 Webby 獎譽為「網際網路的最高榮譽」。國際數位藝術與科學學院 (IADAS) 是表彰網際網路卓越成就的領先國際獎項組織,每年頒發 Webby 獎。

“提名者正在為網際網路上的創新和創意樹立標竿,”Webby 獎主席克萊爾·格雷夫斯說。“在我們今年收到的近 14,000 件作品中脫穎而出,這是一項非凡的成就。”

Wonderous 擁有精美的圖形和獨特的動畫,讓您可以直接從設備中體驗世界奇觀。Wonderous 使用 Flutter 建立一個富有表現力的使用者介面,適合行動裝置的尺寸,並且不符合標準設計系統。相反,它實現了設計師的創意願景。

您可以從 App StorePlay Store 下載 Wonderous。您可以在 這裡 了解自適應設計、動畫、效能和無障礙方面的最佳實務,也可以查看 完整的原始碼

作為提名人,Wonderous 也可能贏得 Webby 人氣獎。這將是全球粉絲的線上投票。從現在到 4 月 20 日,Wonderous 粉絲和 Flutter 開發人員可以在 Webby 獎網站 上投票。


Wonderous 榮獲 Webby 獎提名 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】Flutter in 2023: strategy and roadmap

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

2023 年的 Flutter:策略與路線圖

作為一個開源專案,我們相信在我們對路線圖保持透明時,我們才能最好地服務我們的客戶。

對於採用 Flutter 等技術的開發人員來說,僅僅提供一組有用的功能還不夠。對 Flutter 的依賴也是對維護技能集和程式碼庫的長期承諾。因此,我們必須闡明一個令人信服且切合實際的願景和方向。我們希望分享更多關於我們(Google)為什麼投資 Flutter 的資訊,讓您對我們的未來和方向更有信心,並讓您能夠更清楚地規劃您的投資如何與我們的投資相連接或補充我們的投資。

**因此,我們今天分享了 2023 年策略文件**,其中我們表達了我們的宗旨和指導原則,並描述了我們計劃在今年剩餘時間裡進行的主要投資。出於必要性,我們進行了一些輕微的修改(例如商業敏感資料或對未發布產品的參考),並且像所有計劃一樣,我們不期望這個計劃能夠在面對現實時倖免於難。此策略文件應與我們 wiki 上的 工程路線圖 一起閱讀,該路線圖提供了我們正在開發的特定功能的更多細節。

最後,在以上句子中使用「我們」一詞很重要,這可能會被理解為「那些 Google 支付薪水讓他們在 Flutter 上工作的人」。我們希望 Flutter 貢獻者遠遠多於僅僅是 Google 的員工,但我們不聲稱代表他人的動機或他們可能獨立進行的工作。我們對這種合作表示衷心的感謝。


2023 年的 Flutter:策略與路線圖 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

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

【文章翻譯】Introducing Realm for Dart & Flutter

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

案例研究:使用 Dart 平台原生指令建立一個豐富的跨平台函式庫,支援 Dart 和 Flutter 應用程式

我們很興奮地看到 MongoDB 今天宣布 Realm for Dart 和 Flutter 的正式發佈!Realm 是一個反應式、面向物件的跨平台資料庫,在應用程式開發人員中很受歡迎。換句話說,它非常適合 Dart 和 Flutter。因此,在過去的一年中,我們與 MongoDB 合作將 Realm 帶到 Dart 和 Flutter。查看 MongoDB 發布的 部落格文章,了解 Realm 提供的功能、自早期預覽版以來的改進以及未來計畫。我們認為 Realm 將非常適合 Dart 和 Flutter 開發人員。

使用 Dart 將書籍寫入 Realm 資料庫

在這篇伴隨文章中,我們將透過幕後一窺 Realm for Dart 和 Flutter 的建立過程,作為一個實際的範例,說明如何建立新的基於 Dart 的開發人員 SDK。

Realm 範例

在深入探討 Realm SDK 的實作之前,讓我們先從快速了解如何使用 SDK 作為在 Dart 終端應用程式 上工作的開發人員開始(注意:Flutter 應用程式的步驟略有不同;請參閱 文件 以獲取詳細資訊)。

首先,您定義資料模型。這可以使用帶有額外 Realm 注解的普通 Dart 類別來完成。以下是一個書籍的範例資料類別:

定義好模型,並完全生成資料模型(見下文)後,您可以開始將一些書籍寫入 Realm 資料庫:

Realm for Dart 和 Flutter 是如何建立的

既然我們已經涵蓋了基本知識,讓我們看看 MongoDB 團隊是如何使用許多 Dart 函式庫和工具建立 Realm for Dart 和 Flutter。我們將看看在初始化 Realm SDK 時會發生什麼,Realm SDK 如何建立在一個共用原生 C++ 函式庫之上,Realm 終端工具是如何建立的,以及 Realm 模型是如何生成的。

初始化 Realm SDK

Dart 和 Flutter 開發人員將首先將 Realm 加入到他們現有的應用程式中,然後運行安裝程式:

1
2
dart pub add realm_dart
dart run realm_dart install

第一步只是將 Realm SDK 加入到 pubspec.yaml 中,以 註冊它作為應用程式的相依。第二步運行 Realm 終端工具,要求它安裝 SDK。如果我們查看 安裝指令的原始碼,我們可以看到安裝會確定我們正在開發的作業系統,然後下載該作業系統的 Realm SDK 二進位檔案。

但是為什麼安裝指令要下載二進位檔案?Realm SDK 是一個非常全面的產品,可以在各種作業系統和開發人員框架上使用。為了避免必須建立大量 Realm SDK 的實例,Realm 團隊決定將核心 Realm SDK 實作為一個共用的 realm-core C++ 函式庫。因此,安裝指令真正做的事情是下載這個核心函式庫的編譯版本,適用於應用程式支援的所有平台。

調用 realm-core SDK

使用 Realm SDK 撰寫 Dart 或 Flutter 應用程式的使用者可以獲得不錯的強類型 Dart API,如本文開頭所示。這些 API 如何與 realm-core C++ 函式庫相對應?

如果我們瀏覽 Realm SDK 的 lib 目錄,我們會找到 realm_bindings.dart,它以以下內容開頭:

謎團解開了:Realm SDK 使用 Dart 對原生 API 的互操作性支援(透過 dart:ffi 函式庫)來調用 realm-core。為了避免必須為大量可用的 Realm API 手動撰寫 FFI 綁定,這些綁定是使用 Dart 的 ffigen 工具自動生成的。這是我們在 Dart 團隊中看到快速發展的模式。

Realm 終端工具

讓我們轉向 Realm 終端工具本身。在上面,我們運行了安裝指令,但我們也可以在沒有指定指令的情況下運行這個工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ dart run realm_dart
Realm commands for working with Realm Flutter & Dart SDKs.

Usage: dart run realm|realm_dart <command> [arguments]

Global options:
-h, --help Print this usage information.

Available commands:
generate Generate Realm objects from data model classes
install Download & install Realm native binaries into a Flutter or Dart project
metrics Report anonymized builder metrics to Realm

Run "dart run realm|realm_dart help <command>" for more information about a command.

您可能會注意到這個輸出看起來很像核心 dart 和 flutter 工具的輸出。這不是巧合;所有三個工具都是使用相同的 Dart 基礎函式庫建立的,這些函式庫來自 package:args,專門用於終端工具:

  • args 函式庫對將原始命令列參數解析為選項和標誌有豐富的支援。
  • command_runner 函式庫提供工具支援的指令結構(例如,安裝)。

生成 Realm 模型

生成指令特別有趣,因為它根據我們在「Realm 範例」章節中定義的帶有注解的 Dart 模型類別生成完整的 Realm 模型:

1
dart run realm_dart generate

生成指令是如何工作的?它依賴於 Realm 生成器,該生成器建立在 Dart 的 build_runner 之上,這是一個用於生成器的框架,它接收一組輸入檔案,然後建立新的輸出檔案。通常 - 如 Realm 案例 - 輸入是帶有注解的 Dart 原始碼檔案,輸出檔案是額外的生成的 Dart 原始碼。

結語

希望您喜歡這次對大型開發人員框架如何從一組可重複使用的 Dart 函式庫中建立起來的幕後一窺。如果您是框架開發人員,希望這能为您提供一些靈感,激發您下一个基於 Dart 的框架的構思。

對於 Dart 和 Flutter 應用程式開發人員來說,Realm 是 MongoDB 團隊提供的一個很棒的新產品。我們邀請您查看 Realm SDK 文件 以及今天的 Realm 部落格文章


介紹 Realm for Dart 和 Flutter 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

undefined

【文章翻譯】What’s next for Flutter

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

肯亞奈洛比 Flutter Forward 活動上的願景分享

今天,我們很興奮能夠在 Flutter Forward 上與大家分享我們對 Flutter 的願景。Flutter Forward 是我們的開發者活動,正在從肯亞奈洛比現場直播,來自世界各地的開發者們齊聚一堂,線上線下同步參與,了解 Flutter 未來的發展方向。

Flutter 是一個 UI 工具包,讓應用程式開發者能夠從單一程式碼庫為行動、網頁和桌面構建應用程式。Flutter 使您能夠構建 美麗 的應用程式,讓您能夠完全控制螢幕上的每個像素。它 速度快,利用手機或電腦的硬體,支援硬體加速圖形和原生編譯的機器碼。它 生產力高,擁有狀態熱重載等技術,讓您能夠立即在應用程式中看到程式碼變更。它的 可移植性 使您能夠使用相同的原始碼部署到各種平台,而且不會有任何意外。而且它完全 開源,不需要支付許可費,也不需要為開發工具付費。

Flutter 已證明其受歡迎程度,迄今已發佈超過 700,000 個應用程式:從具有 非凡想法的小型新創公司具有關鍵需求的大型企業。在 Google,我們也發現 Flutter 是一個寶貴的工具,讓 Google Classroom 等團隊能夠為行動和網頁使用者提供高品質的解決方案;我們還在其他開發者工具中加入對它的支援,包括 Google 廣告Google 地圖Google Pay,當然還有 Firebase

“使用 Flutter,我們將相同功能的程式碼大小減少了 66%... 這意味著每個平台的錯誤更少,未來技術債務也更少。”(Kenechi Ufondu,Google Classroom 軟體工程師)

Flutter 的第一個版本提供了一個 UI 工具包,用於在 Android 和 iOS 上構建行動應用程式,但隨著 Flutter 3 的推出,我們將生產支援擴展到包含 Windows、macOS、Linux 和網頁,同時也讓嵌入式平台能夠使用 Flutter。在此基礎上,本週我們發佈了最新的穩定版本 Flutter 3.7,其中加入了一系列新功能,包括 iOS 上的新渲染引擎、增強對 Material 3 和 iOS 風格 Widget 的支援、改進的國際化支援、背景處理改進以及開發者工具更新。

但在這次活動中,我們將目光 展望未來,預覽我們在 Flutter 上的下一波投資:突破性的圖形效能、網頁和行動的無縫整合、對新興架構的早期支援,以及持續關注開發者體驗。我們將展示將在未來幾個月內逐步交付的工作,我們希望這能讓您對我們對 Flutter 的願景感到興奮,Flutter 將成為任何希望構建高品質、美麗使用者體驗的開發者的強大工具包,這些體驗可以應用在有像素的地方。

免責聲明:我們在此預覽的功能仍在開發中,可能會在未來幾個月內發生重大改變。在這個早期階段展示它們的目的是讓早期採用者有機會做出貢獻。

四個主題:突破性的圖形效能、網頁和行動的無縫整合、對新興架構的早期支援,以及持續關注開發者體驗。

突破性的圖形效能

從歷史上看,跨平台框架需要在視覺效果上做出妥協,因為創建抽象層存在挑戰。Flutter 採用了與大多數框架不同的方法,它擁有自己的渲染層,提供硬體加速圖形,並在每台設備上呈現一致的視覺外觀。展望未來,我們將投資於 突破性的圖形效能,擴展 Flutter 在這個領域的既有優勢。

在 Flutter Forward 上,我們展示了在 Impeller 上的更多進展,Impeller 是 Flutter 的下一代渲染引擎。Impeller 針對 Flutter 優化,為我們提供了更大的靈活性,並能夠更好地控制圖形管道,為我們打開了新的機會。Impeller 提供更可預測的效能,使用預先編譯的著色器,消除由著色器編譯引起的運行時掉幀。它利用 Metal 和 Vulkan 中的基元,這些是 iOS 和 Android 中的現代低階 API。而且它有效利用併發性,將單一框架工作負載分配到各個執行緒。

Impeller 為 Wonderous 等需要大量圖形處理的應用程式提供絲般順滑的效能,Wonderous 是一個美麗的應用程式,帶領您遊覽世界奇觀。如圖所示:Wonderous 的最新版本,它調整 UI 以適應不同的設備和外觀比例,可在 [https://wonderous.app](https://wonderous.app.) 上使用。

除了提供絲般順滑的 UI 之外,Impeller 還可以在某些情況下顯著提高效能。一個示範(如下所示)展示了這個最佳案例。左側是一個使用 SVG 剪裁的萬花筒應用程式,使用當前的預設渲染器構建。向下捲軸頁面時,效能下降,渲染時間超過每幀預算,導致幀速率為 7-10 fps。右側顯示了在 Impeller 下運行的相同應用程式,以無卡頓的 60 fps 渲染。

從零開始構建的一個優勢是架構可以支援全新的用例。新引入的 對自訂著色器的支援 已經導致了一些 令人驚嘆的新示範,展示了與 Flutter Widget 階層的無縫整合。但是,我們在此的工作不僅限於行動設備:我們現在也對網頁上的自訂著色器提供了早期支援,相同的程式碼現在為 iOS、Android 和瀏覽器提供硬體加速的體驗。

Chrome 網頁瀏覽器的螢幕截圖,顯示 Flutter 像素著色器示範。有一個 Flutter 吉祥物 Dash 的圖片,但它有一個馬賽克風格的效果,可以使用滑動控制調節。
Flutter 現在支援網頁上的像素著色器,能夠實現各種很酷的視覺效果。(作者: [Erick Ghaumez](https://medium.com/u/21767146c3d4)。)

現在,我們開始了對 使用 Flutter 支援 3D 的早期工作。在主題演講中,我們展示了您可以匯入使用 Blender 創建的模型,甚至可以使用熱重載來與 Blender 實時互動,并在正在執行的應用程式中查看結果。這還處於起步階段,但我們對初始性能感到興奮,以及將 3D 整合到其他 Flutter 體驗的潛力。

Impeller 使 Flutter 能够渲染 3D 图形,如 Dash 的这个有趣演示所示。

在可移植的 UI 工具包中加入 3D 和自訂著色器,將圖形效能提升到一個新的水平。我們非常期待您在這些新功能可用後使用它們做出的成果。

網頁和行動的無縫整合

雖然您可以完全使用 Flutter 和 Dart 撰寫應用程式,但幾乎任何非微不足道的專案都需要與其他程式碼連接。在網頁上,Flutter 可以作為較大應用程式中的嵌入式組件使用;在行動裝置上,應用程式可能需要呼叫系統 API 或其他使用其他語言編寫的程式碼。因此,我們投資的第二個主要主題是 網頁和行動的無縫整合

在網頁上,我們正在預覽一個我們稱之為 元素嵌入 的新功能,它允許將 Flutter 內容新增到任何標準網頁 <div>。以這種方式嵌入時,Flutter 只是一個網頁組件,可以與網頁 DOM 整合,甚至可以允許使用 CSS 選擇器和轉換來設定父 Flutter 物件的樣式。

我們還在對 js 套件做出一些重大改變,以實現 JavaScript 和 Dart 程式碼之間的無縫 互操作性。使用 js,您可以在 Dart 程式碼中使用 @JSExport 屬性對任何函數進行註釋,然後從 JavaScript 程式碼中呼叫它。

結合這兩個新功能,為在網頁上使用 Flutter 開啟了一些令人興奮的新場景。在我們在 Flutter Forward 上展示的 概念驗證示範 中,您可以看到一個嵌入在基於 HTML 的網頁中的簡單 Flutter 應用程式。使用 CSS,我們應用了一個動畫旋轉效果;即使在旋轉時,Flutter 內容仍然可以互動。示範還顯示,您可以使用 HTML 按鈕和 JavaScript 事件處理程式來更改 Flutter 狀態,反之亦然。當這項工作完成後,我們認為這將為使用 Flutter 將互動性加入到現有的 Web 應用程式中開啟許多新的機會。

Flutter 網頁示範的螢幕截圖。顯示了傳統的 Flutter 計數器應用程式,但它被 CSS 扭曲和轉換,看起來像是照片的一部分,照片中一位女性拿著一部 iPhone。
使用元素嵌入,您可以在 `
` 元素中嵌入 Flutter,並使用 CSS 為其設定樣式。

轉向 Android 和 iOS,Flutter 已經長期支援使用平台通道與系統 API 整合,平台通道為使用 Kotlin 或 Swift 等語言編寫的程式碼提供了基於訊息的通訊方式。雖然這解鎖了對這些函式庫的存取,但它需要應用程式作者熟悉多種語言,並且需要大量的樣板程式碼。

我們現在開始了 針對系統互操作性的新方法 的工作,允許直接呼叫函式庫。在 iOS 上,我們正在建立在 FFI 用於 C 互操作性的工作基礎之上,加入對 Swift 和 Objective-C 函式庫的支援。在 Android 上,我們正在使用 JNI 來橋接到用 Kotlin 編寫的 Jetpack 函式庫。使用新命令,Dart 會自動為跨語言互操作創建綁定,並適當轉換資料類別。完成後,我們希望這項工作能夠讓 Flutter 開發者能夠呼叫新的 Jetpack 或 iOS 函式庫,而無需使用外掛或學習不同的 API 語法,同時也能大大減輕外掛作者的工作。查看我們的範例 了解更多!

對新興架構的早期支援

由於 Dart 廣泛支援各種處理器架構,以及它高度優化的 JavaScript 編譯器,Flutter 已經可以在各種設備和外觀比例上執行。但隨著一些令人興奮的新選項即將出現,我們第三个主題是 對新興架構的早期支援

WebAssembly 作為一種平台中立的二進制指令格式,已日漸成熟,在現代瀏覽器上獲得了 越來越多的支援。令人興奮的是,WebAssembly 為網頁平台打開了除了 JavaScript 之外的其他語言的大門。在最近幾個月裡,我們一直在與 Chrome 團隊和其他 WebAssembly 合作夥伴合作,為 垃圾回收語言(如 Dart)提供 早期支援。此 WebAssembly 的新擴展現在使用最新開發版本的 Chrome 中的旗標支援。在 Flutter Forward 上,我們正在揭示對 Flutter 編譯為 WebAssembly 的早期支援,這將為我們的 Web 支援帶來更快的速度和更小的佔位空間優化。

另一個引發越來越多人興趣的平台架構是 RISC-V,這是一種開放標準指令集架構 (ISA),旨在廣泛使用。Android 團隊最近發表了關於 他們支援 RISC-V 的工作 的演講,我們很高興地宣布 Dart 現在也支援 RISC-V,作為了我們自己的旅程的一部分,讓 Flutter 能夠在 RISC-V 設備可用時在其上執行。生產 RISC-V 硬體仍處於起步階段,但在 Flutter Forward 上,我們展示了迄今在 ClockworkPi DevTerm Kit R-01 上取得的進展,這是一款運行 Linux 的自組裝便攜式終端機。我們相信 RISC-V 支援將特別適用於嵌入式方案,Flutter 可以為各種需求提供強大的 UI 工具包。

ClockworkPi RISC-V 便攜式終端的圖片。這是一個大約與 iPad 大小相同的設備,但帶有微型鍵盤、軌跡球滑鼠和終端機顯示器。
ClockworkPi DevTerm R-01,一款實驗性的 RISC-V 電腦,運行 Dart 主控台應用程式。

持续关注开发者体验

我们上面描述的所有内容的基础都是开发人员的生产力,这是 Flutter 自创建以来一直以来的标志,其功能包括状态热重载。我们对未来的第四个也是最后一个投资领域是 持续关注开发人员体验,涵盖 Flutter 和 Dart。

在 Flutter Forward 上,我们正在预览我们对一些主要的 Dart 语言新功能的早期工作的部分成果,我们希望这些成果能够证明我们对语言的优雅演进的承诺。在我们的开发频道中,我们现在拥有对 记录和模式 的早期支持,这两个新增强功能可以很好地配合使用。

VSCode 运行记录和模式新功能演示的图片。它显示了 Dart 现在可以返回多个值。演示的代码位于 https://gist.github.com/timsneath/a75fd9f76b5b61c42676c9232160d14d
记录和模式用于返回和接收多个函数参数的简单示例。

我们还 正式宣布 Dart 3,这是我们为语言引入健全的空安全而开展的工作的顶峰。Dart 3 还删除了其他长期弃用的功能,以进一步使语言现代化。我们已经开始发布 Dart 3 的 alpha 版本,以及匹配的 Flutter 版本,使开发人员能够测试包和应用程序。有关 Dart 3 的更多信息,请查看 Dart 通道的单独博客文章

当然,我们也会投资于 Flutter 的开发人员体验。继我们去年在 I/O 上发布的休闲游戏工具包取得成功之后,我们现在正在共享 第一个版本的新闻工具包,它可以加速新闻出版商和其他希望触达移动用户,而不必从头开始设计应用程序的內容提供者的移动开发。它包括构建以文章为中心的应用程序所需的一切,包括导航和搜索、身份验证、广告整合、通知、个人资料和订阅,同时还将 Google 新闻倡议研究的最佳实践整合在一起。今天,我们重点介绍了非洲的三个早期采用者,他们正在使用这个工具包构建应用程序,包括 Hespress,摩洛哥最大的新闻网站之一,Bold Sports,尼日利亚受欢迎的体育网站;以及 The Standard,肯尼亚最古老的报纸。

携手共进

我们希望您与我们一起对 Flutter 的未来感到兴奋。我们正在继续大力投资核心开发人员体验,同时进行一些基础改进,为我们和其他人铺平道路,以便使用 Flutter 构建更强大的体验。

这张图片总结了我们的方向:

未来工作的四个主题:突破性的图形性能(Impeller、着色器、3D 支持);网页和移动的无缝集成(元素嵌入、JNIgen 和 FFIgen);对新兴架构的早期支持(WebAssembly 和 RISC-V);以及持续关注开发者体验(Dart 语言特性、健全的空安全、Google 新闻工具包和 Wonderous)。

除了我们自己的开发主题之外,看到 Flutter 生态系统不断扩展也令人欣慰,例如 FlutterFlow 是一個開發原生行動應用程式的低程式碼建構器,以及 Widgetbook,它提供靈活的工具,讓設計師和開發者能夠在使用者介面開發上進行合作。

最后,来到肯尼亚,看到当地开发者的创业精神和才华,真是太好了。非洲的 Flutter 社区充满活力,这里很特别;仅 Flutter 肯尼亚用户组的开发人员就超过 1,000 人。我们很高兴 Flutter 能为非洲各地的开发人员提供新的机会,让他们参与到快速增长的应用程序经济中。Klasha 就是这个承诺的一个很好的例子,它使用 Flutter 快速进入市场,并解决当地的难题。以下是他们使用 Flutter 的体验视频:


Flutter 的下一步是什麼 最初發表在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

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

【文章翻譯】Adapting Wonderous to larger device formats

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

使用 Flutter 設計在所有設備上看起來都美觀的行動應用程式

今天,我們宣布 Wonderous 的下一個版本,該版本新增了對可折疊設備、平板電腦和平板電腦橫向模式的支援。這個迭代讓我們能夠測試 Flutter 適應不同設備格式 的能力,GitHub 上的 程式碼 存放庫提供了利用 適應性設計 的參考。

在本文中,我們將回顧我們在其中學習到的一些內容。雖然我們的重點是手持設備的應用程式,但其中許多概念可以適應桌面和網頁。

縮小焦點

在思考適應性設計時,設計師應該首先問:「我們可能支援哪些外形尺寸?」Flutter 支援幾乎所有設備,但應用程式創建者應該明確說明他們設計和測試過其應用程式的格式。縮小焦點讓設計師可以仔細考慮如何為可用的畫布最佳化數位體驗。沒有仔細設計,適合行動裝置的佈局在較大的外形尺寸上可能看起來不精緻。

充分利用額外的空間

在適應應用程式設計以符合更大的螢幕尺寸時,設計師應該考慮如何利用額外的空間。這可能意味著透過顯示不同的佈局來增強呈現方式。例如:

Portrait and landscape version of the Wonder Events page
iPad Pro 12.9 英寸直立和橫向

新增額外的行或欄:

Showing the artifcats search results on a larger screen with 4 columns, versus a smaller screen with only two columns
iPad Pro 12.9 英寸和 iPhone 11

或將欄變為行:

Showing vertically scrollable rows in portrait mode, and a single horizontally scrollable row in landscape.
iPad Pro 12.9 英寸直立和橫向

或者,您也可以使用額外的畫布來做更多相同的事情。Wonderous 具有美麗的插圖,因此更大的螢幕尺寸讓我們能夠展示更多這項工作:

Showing an image of the Machu Picchu illustration scaled to multiple devices sizes
iPhone 11,Samsung Fold4 關閉,iPad Pro 12.9 英寸

考慮 UI 組件如何反應的方式

隨著螢幕變大,您需要考慮應用程式的 UI 組件將如何反應。例如,您可能需要將組件縮放到適合可用空間的大小:

Samsung Fold4 打開和 iPhone 11

您也可以考慮保持內容居中加權,或將某些資產固定到設備邊界:

使用 Flutter 的適應性設計

Flutter 架構中有許多功能對適應 Wonderous 很有幫助。例如:

  • 熱重載讓設計團隊能夠實時做出微調
  • 動態填充和字體大小
  • Flex Widget 動態顯示行或欄
  • MediaQuery 返回螢幕尺寸和設備方向等詳細資訊

您可以在 gSkinner 的網站 上閱讀有關技術實作的更多具體資訊。您還可以在 Android 文件網站上的 大型螢幕應用程式尺寸 中了解有關為更大螢幕尺寸設計應用程式的更多資訊。

我們希望您能安裝 Wonderous,並在開發您自己的應用程式時將程式碼用作參考。如果您對應用程式本身有任何回饋,請 在 GitHub 上提交議題。如果您對使用 Flutter 的適應性設計有任何想法,請隨時透過 Twitter (@leighajarett) 或 LinkedIn (Leigha Jarett) 傳送訊息給我。


將 Wonderous 適應更大的設備格式 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】Introducing Dart 3 alpha

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

介紹 Dart 3 alpha

12 月,我們發表了第一篇關於 Dart 3 的部落格文章,讓我們得以一窺未來。今天,在肯亞奈洛比舉行的 Flutter Forward 開發者活動現場,我們分享了 Dart 下一個主要版本的更廣泛願景,以及我們的第一個預覽版本 Dart 3 alpha

我們的 Dart 使命是創造最好的程式語言,以便在任何應用程式平台上構建高品質的應用程式。Dart 易於上手、易於學習,避免不必要的複雜性,並且內部一致。Dart 生產力高;應用程式開發人員面臨著持續的壓力,需要在更短的時間內交付具有不斷變化的需求的應用程式,同時還要保證品質和完成度。因此,我們在構建 Dart 時,非常注重實現快速開發、快速迭代和高品質。Dart 還具有 可移植性,涵蓋最廣泛的平台,使您能夠將應用程式部署到現在和未來的設備上。

多年來,我們一直致力於建立這些品質。藉由 Dart 3,我們打算邁出更大的一步,以顯著的方式改進和擴展易用性、生產力和可移植性。

Dart 3 是一個全新的 主要 版本。部分原因是為了表示新功能的重大進展,部分原因是就語義版本控制而言,它是一個 重大變更版本:我們正在將類型系統更改為 支援 完善的空值安全(在 Dart 2.12 及更高版本中,這是 可選的),並在 Dart 的核心函式庫中進行了相應的重大變更。讓我們深入了解細節!

Dart 3 生產力提升

更具表現力的 Dart 語言:記錄、模式和存取控制

過去幾年,我們以飛快的速度發展 Dart 語言,自 2.0 版以來 新增了 23 項新功能。在 Dart 3 中,我們預計會新增兩項主要功能,即記錄和模式,目標是讓使用結構化資料更有效率。

記錄允許您有效且簡潔地從任何現有資料建立匿名複合值,而無需宣告類別來儲存這些值的思維負擔。使用記錄,您可以輕鬆構建組合現有資料的新資料結構。例如,要返回一對值:

1
2
3
4
(int, int) geoLocation(String address) {
// ...
return (lat, long);
}

記錄允許您組合資料,而模式可以將複合資料解構為其組成部分。例如,要將上面 geoLocation 的返回值(由一對整數組成的記錄)解構為兩個單獨的整數變數 latlong,您可以使用如下模式宣告:

1
var (lat, long) = geoLocation(address);

模式是完全類型安全的,並在開發過程中進行檢查。

您還可以根據值的類型進行模式匹配,例如從類別的階層結構中匹配。switch 可以使用與類型匹配的模式,以及每種類型的單獨欄位,如下所示 calculateArea 的主體:

1
2
3
4
5
6
7
8
9
10
double calculateArea(Shape shape) {
return switch (shape) {
Square(side: var s) => s * s,
Circle(radius: var r) => pi * r * r,
Rectangle(
width: var w,
height: var h
) => w * h,
};
}

總體而言,我們正在添加大量模式,這些模式組合在一起使 Dart 在處理結構化資料時更具表現力。

結合模式,我們還透過幾個新的修飾符為類別新增了 能力控制

  • interface class:不能被繼承。
  • base class:禁用隱式介面,因此不能被實作。
  • final class:不能繼承、實作或混合使用該類別(在目前的函式庫之外)。
  • sealed class:與 abstract + final 相同,並且該類型被視為密封類型族的根,用於窮盡性檢查。例如,以上面的 Shape 類別階層為例。在 Shape 類型的 switch 語句中(如 calculateArea 函數),如果 switch 語句未處理密封類型的所有可能子類型,分析器將觸發錯誤。
  • mixin class:可以用作 mixin 的類別。

每個新功能都會增加語言的複雜性。為了確保 Dart 保持易於上手,類別預設是完全允許的,就像今天一樣,只有一個小例外,即打算用作 mixin 的類別現在必須使用 mixin 關鍵字。

透過直接平台函式庫互操作實現高效的平台整合

我們正在努力擴展 Dart 語言的互操作性,以便 直接從 Dart 調用平台函式庫。在 Apple 平台上,我們正在基於我們在 FFI for C interoperability 上的工作,它支援從 Dart 調用任何遵循 C 調用約定的 C 模組。到目前為止,它支援 C、Go 和 Rust 等語言。現在,我們正在為 iOS/macOS 上的 Swift 和 Objective-C 新增支援。在 Android 上,您可以利用 FFI 和 Android 的 Java Native Interface (JNI) 調用以 Kotlin 編寫的 Jetpack 函式庫和以 Java 編寫的 Android 函式庫。

在新的工具的支持下,Dart 可以根據原始 C/ObjC/Swift/Java/Kotlin 程式碼的標題/介面檔案自動建立具有 Dart 介面的繫結,以及這些繫結背後的跨語言互操作程式碼。有關使用此方法調用 Apple 的 Core Motion API 和 Android 的 HealthConnect API 的示範,請查看 範例應用程式

這些新的互操作機制目前尚處於實驗階段,但我們希望它們至少能在 Dart 3.0 穩定版中達到 beta 品質。我們歡迎您在 Java/KotlinC/ObjectiveC/Swift 的問題追蹤器中提供回饋。最後,我們也在努力改進 Dart 與 JavaScript 的互操作性;我們將在以後的部落格文章中提供更多相關資訊。

可移植性方面的進展

Dart 已經透過我們的原生和網路編譯器支援廣泛的目標平台。在 Web 上,我們目前編譯為 JavaScript。在原生設備上,我們目前支援 Intel 32 位和 64 位,以及 ARM 32 位和 64 位架構。我們正在努力為許多新興的設備和標準新增支援,以確保 Dart 為未來的設備做好準備。

對於 Web,我們正在努力支援 WebAssembly (Wasm),它作為一個平台中立的二進制指令格式,在 所有現代瀏覽器 中都日趨成熟。我們希望 Wasm 能夠使 Dart Web 應用程式的啟動速度與原生設備上的應用程式一樣快。

另一個越來越受關注的平台架構是 RISC-V,這是一種為廣泛使用而設計的開放標準指令集架構 (ISA)。Android 團隊最近就 他們對 RISC-V 的支援工作 進行了演講,我們認為它也將廣泛應用於嵌入式設備。Dart 3 alpha 中提供了對 RISC-V 的預覽支援。

最後,我們正在努力擴展我們目前對 ARM 設備的支援,使其也涵蓋 Windows 上的 ARM64 支援。

Dart 3 的重大變更

介紹了新的 Dart 3 功能後,讓我們來看看我們為了更一致且更易於上手的 Dart 而進行的重大變更。

Dart 3 類型系統:100% 完善的空值安全

我們在 2021 年的 Dart 2.12 中引入了完善的空值安全。在完善的類型系統中,您可以信任類型,這意味著當類型聲明變數不為空時,它就 永遠 不為空。這提高了生產力,因為可以在開發過程中而不是在生產環境中發現問題,並且使 Dart 編譯器能夠產生 更小、更優化的程式碼。正如我們在 12 月 所討論的,Dart 的獨特之處在於將 100% 完善的空值安全引入到現有語言中。

自 Dart 2.12 起,空值安全一直是一個可以 開啟關閉 的設定選項。在 Dart 3 中,所有程式碼都以 開啟 完善的空值安全運行。不再可以運行沒有空值安全的應用程式或在部分空值安全的混合模式下運行應用程式。

我們意識到停止支援不使用空值安全的運行可能會給現有的應用程式和套件帶來問題。但是,我們覺得現在是推進這一變更的合適時機。擁有一個單一的類型系統,其中空值安全始終開啟,可以減少開銷和複雜性。每當開發人員讀取一段 Dart 3 程式碼時,他們都可以放心,所有變數預設都不為空。在實作方面,Dart 的編譯器和運行時可以專注於支援單一的 Dart 程式碼運行方式,從而降低新增新功能的成本和複雜性。

Dart 生態系統已經展現出將現有程式碼遷移到空值安全的堅定決心和意願。截至今天,

  • pub.dev 上排名前 250 位的套件中有 100% 支援空值安全
  • pub.dev 上排名前 1000 位的套件中有 98% 支援空值安全
  • 只有 14% 的 flutter run 階段仍然在沒有空值安全的情況下運行

感謝生態系統為遷移所做的努力!

清理 Dart 3 核心函式庫和語言

隨著 Dart 語言和類型系統的發展,我們核心函式庫中的一些 API 變得冗餘或不夠理想。為了確保 Dart 保持易於上手,我們進行了一些重大變更以清理不必要的 API。有關詳細資訊,請參閱 GitHub 問題,#34233#49529。我們還移除了一個歷史語法,用於預設參數值(#2357)。

隨著 Dart 3 alpha 的完成,我們的注意力現在轉向了 Dart 3 beta。在那裡,我們希望透過新增一些新的 API 來進一步改進 Dart 核心函式庫。您可以在 回饋問題 中提供意見。

準備您的程式碼以迎接 Dart 3 穩定版

一般來說,我們相信大多數已經遷移到使用空值安全(使用 Dart 2.12 或更高版本)的程式碼都可以在 Dart 3 上運行。但是,一小部分套件和應用程式可能會受到上面討論的重大變更的影響。因此,為了讓您有時間準備今年晚些時候發佈的 Dart 3 穩定版,我們沒有計劃在 Dart 3 alpha 之後對 Dart 語言和核心函式庫進行任何進一步的重大變更。

為了利用已經遷移到使用空值安全的程式碼,我們在 Dart 3 中實作了向後相容性,這將允許遷移的套件在 Dart 3 中使用 pub get 解析,即使它們的 SDK 版本限制為 >=2.12 <3.0.0,只要它們不依賴於其他已停止使用的核心函式庫 API 或語言功能。有關更多詳細資訊,包括如何使用本地安裝的 Dart 3 alpha SDK 進行測試,請參閱我們的 Dart 3 空值安全文件

對於發佈在 pub.dev 儲存庫上的套件,我們使用 Dart 3 alpha 進行了分析,並使用 “Dart 3 ready” 標籤標記了通過的套件。這表示該套件很可能在今年晚些時候 Dart 3 穩定版發佈時可以運行。

Dart 3 工具清理

在 Dart 3 發佈之前,我們進行了 許多變更,將我們所有的終端開發者工具都移動到一個統一的 dart 開發者工具中,這使得 Dart 對新開發者來說更容易上手。我們計劃在接下來的幾個月中進行 額外的工具變更 以進一步清理。希望這些變更不會造成太大的破壞,但在 Dart 3 beta 中,工具可能會出現一些小的損壞。

後續步驟

Dart 3 alpha 今天已在 Dart 開發頻道和 Flutter master 頻道中提供。我們邀請您試用它,無論是嘗試記錄和模式等新語言功能,還是嘗試我們新的直接存取平台互操作,或者測試您的應用程式和套件的 Dart 3 相容性

我們將在接下來的幾個月中繼續改進 Dart 3,並希望在今年晚些時候發佈完整的 Dart 3 穩定版。請注意,大多數功能仍在開發中,因此在穩定版發佈之前可能會有所變更。在此之前,祝您使用 Dart 程式碼愉快!


介紹 Dart 3 alpha 最初發佈在 Medium 的 Dart 上,人們在那裡透過醒目顯示和回應這個故事來繼續討論。

【文章翻譯】Announcing the Flutter News Toolkit

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

宣布 Flutter 新聞工具套件

This image shows Dash is reading newspaper

Google 的 Flutter 團隊與 Google 新聞倡議 (GNI) 密切合作,共同打造了 Flutter 新聞工具套件 - 一個免費的預建 Flutter 應用程式範本,用於加速新聞應用開發。一些早期採用者已經在短短 6 週的時間內建立了 iOS 和 Android 應用程式,聲稱與傳統的 iOS 和 Android 雙端開發相比,節省了高達 80% 的時間。

三個月前,我們在早期試用階段宣布了該工具套件,並收到了來自世界各地組織的壓倒性申請,因此我們很高興宣布 Flutter 新聞工具套件的第一個版本現在已正式推出!

為什麼我們要建立 Flutter 新聞工具套件?

如今,大多數人使用智慧型手機獲取新聞。除了行動網站以外,行動應用程式可以成為新聞出版商與現有讀者互動、接觸新受眾以及創造新收入來源的絕佳方式。但設計、實作和部署行動應用程式需要時間和精力。

對於財力和人力資源有限的新聞出版商來說,從頭開始建立應用程式是一項重大工程。在 Google,我們希望幫助開發人員取得成功並提高生產力,因此我們正在投資一個工具套件,該工具套件提供了新聞出版商所需的所有常見功能,讓他們可以專注於區分他們的品牌和內容,而無需撰寫樣板程式碼。

Flutter 新聞工具套件中包含哪些功能?

我們與全球業界專家和新聞出版商合作,以識別新聞應用程式範本的基本功能和使用者工作流程。有了這些預建的開箱即用功能,新聞出版商只需要連接他們的資料源並自訂 UI 以反映他們的品牌。

使用來自 新聞消費者洞察 的最佳實務,Flutter 新聞工具套件包含以下功能:

  • 使用者入門:透過推送通知權限重新吸引您的受眾;取得廣告追蹤權限
  • 帳戶建立/登入:透過您的平台和使用者社群媒體網路進行驗證(例如 Google 登入);建立無密碼帳戶
  • 內容供稿和內容頁面:顯示新聞文章、影片、圖片、廣告和電子報報名提示
  • 變現:輕鬆加入訂閱和不同的廣告格式
  • 搜尋:允許使用者透過關鍵字搜尋文章或點擊熱門搜尋項目
  • 設定:允許使用者針對通知、登入和廣告追蹤調整偏好設定

您可以直接使用這些預整合功能,也可以輕鬆地修改並將它們替換為您偏好的其他功能。

This image includes sample features provided in the Flutter News Toolkit
Flutter 新聞工具套件中提供的範例功能

早期採用者

Flutter 新聞工具套件已經開始幫助全球各地的新聞出版商加速行動策略並實現業務目標。例如,

  • The Standard(肯亞最大的新聞出版商之一)在建立 The Standard 新聞 時,聲稱節省了高達 80% 的時間。
  • 商業賦能公司 AnyMind Group 在 2 週內為 Khaosod Online(泰國最大的新聞網站之一)建立了應用程式。
  • Boldsports,一家尼日利亞的體育新聞新創公司,在短短幾天內就建立了一個早期版本。
  • Hespress(摩洛哥最大的新聞網站之一)在 6 週內完成了其 英文應用程式 開發,並報告說新應用程式在推出應用程式後的兩個月內, organically 獲得了 93% 的有機使用者,廣告收入增長了 50%。

讓我們用他們自己的話聽聽他們的感受。

開始使用

如果您一直在等待存取 Flutter 新聞工具套件,現在可以開始了!您現在可以直接存取 Github 上託管的程式碼

如果您有興趣採用新聞工具套件,但需要幫助自訂以滿足您的需求,我們也為您提供了支援!只需發送電子郵件至 [email protected],我們可以推薦值得信賴的 Flutter 代理商來幫助您使用 Flutter 新聞工具套件建立應用程式。

雖然 Flutter 新聞工具套件最初是為新聞組織設計的,但任何想要建立流程式內容的人都可以使用範例程式碼。無論您是想建立公司電子報應用程式(以 DiUS 建立的 Medius 為例),還是社群媒體應用程式,您都可能會發現使用者登入、社群分享和內容供稿等預建功能對您的應用程式有所幫助。

我們計畫繼續改進 Flutter 新聞工具套件,同時從出版商和開發人員那裡獲取更多資訊。別忘了查看我們的 影片教學,以瞭解 Flutter 新聞工具套件 的更多詳細資訊!

常見問題解答

什麼是 Flutter?

Flutter 是 Google 的開源 UI 工具套件,用於從單一程式碼庫建立適用於行動裝置、網頁和桌面的精美應用程式。Flutter 大幅減少了建立和發佈應用程式所需的時間。如今,Flutter 是 最受歡迎的跨平台 開發框架,在全球擁有超過 300 萬名開發人員。目前有超過 700,000 個 Flutter 應用程式,包括阿里巴巴、BMW、Google Pay、PUBG、Shein 和微信。

Flutter 容易學習嗎?

是的,對於那些了解 Java 等其他程式設計語言的開發人員來說,學習 Flutter 速度很快。此外,我們還為您提供了豐富的 學習資源 來幫助您入門。

我可以在應用程式中使用其他非 Google 服務,例如廣告、分析和訂閱嗎?

當然可以!Flutter 新聞工具套件只是一個範例。您不需要使用任何您不想要的服務。事實上,很容易移除或將現有整合替換為其他服務。例如,如果您想使用非 Google 廣告服務,您可以在 pub.dev 上找到其他 套件

我需要做多少工作才能發佈應用程式?

雖然新聞範本可以降低建立新聞行動應用程式的入門門檻,但此解決方案仍然需要 Flutter 開發工作。範本不支援非技術使用者透過無程式碼或所見即所得功能或工具(例如儀表板)來修改應用程式品牌和樣式。

我們已繪製出一個高層級的部署流程圖,假設有 2 名 Flutter 工程師參與專案。例如,Hespress 等早期採用者在 6 週內完成了應用程式開發。但我們也有像 AnyMind 這樣的客戶,他們只用 1 名工程師在 2 週內就推出了應用程式。

This image maps out the deployment process at a high-level
高層級的部署流程

如果我沒有內部的開發團隊,如何使用範本?

我們可以推薦值得信賴的 Flutter 代理商,他們可以幫助您將範本完善。您可以發送電子郵件至 [email protected] 獲取更多資訊。聲明:Google 與這些代理商無關,我們也不從他們那裡分享任何收入。


宣布 Flutter 新聞工具套件 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】Better isolate management with Isolate.run()

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

使用 Isolate.run() 更好地管理 Isolate

Dart 2.19 引入了一個新函數,可以讓您僅用一行程式碼即可輕鬆實現併發。

展示新 Isolate.run() 函數速度的基準測試

所有 Dart 程式碼都在 isolate 中運行。是否要實作多個 isolate 以在 Dart 程式中啟用 併發 取決於您。如何實作多個 isolate 則取決於 Dart 團隊,在 Dart 2.19 中,我們對此流程進行了巨大的升級,我們很興奮能與大家分享。來認識一下 Isolate.run() 吧!

run() 將設定和管理 isolate 的所有複雜性完全抽象成單個函數調用。使用一些基本元素來使用 isolate 已經有一段時間了。但是,即使 isolate 有了所有最近的效能改進,這個過程充其量也只是繁瑣的,最糟糕的情況下則容易出錯。

為了讓您了解 run() 的改進程度,本文將逐步分解先前使用低階基本元素建構功能的方法。然後,我們將其與使用 Isolate.run() 進行對比,並向您展示它在內部的運作方式。即使您以前從未使用過 isolate,我們也相信 run() 會讓您興奮地想要嘗試它們!

Isolate

Isolate 是一個相當簡單的概念。Isolate 本質上是 Dart 中的單個執行緒。它們讓您可以並行執行部分程式碼。您可以啟動新的並行執行(數量不限),並直接從 main(主執行緒或 main isolate)告訴它們要做什麼。Isolate 不共享記憶體;相反,它們透過來回傳遞訊息來進行通訊。因此,您不必擔心典型的多執行緒問題,例如競爭條件或互斥鎖和鎖。

聽起來很棒!但是如何使用它們呢?在 Isolate.run() 之前,事情變得棘手起來。

Isolate API 由低階基本元素組成,這些基本元素提供了廣泛的功能。當您需要自訂 isolate 的功能時,這種粒度非常棒。但是,當 必須 使用 isolate 時,這種粒度就不那麼好了。特別是因為幾乎所有 isolate 的使用案例都需要相同的設定和管理基本配置。這基本上意味著要將每個實作細節都公開給 Dart 的使用者自行處理。

讓我們來看看典型的 isolate 設定,以更好地理解 Isolate.run() 所解決的繁瑣過程。

使用 Isolate(之前)

您可以將 Isolate.spawn() 視為 isolate 的舊起點。Flutter 的 compute 函數就是建立在 spawn() 之上的。它接受一個方法作為其入口點參數,以及該方法的任何參數,以及 isolate 本身的其他配置。過去,此入口點只能是頂級或靜態方法。

1
Isolate.spawn(_readAndParseJson, filename);

Isolate 建立完成!開玩笑的。還差得遠呢。

調用 spawn 不會返回任何實際可用的東西。它只返回一個 isolate 物件,該物件只是確認 isolate 已啟動。

除了建立時傳遞的初始參數之外,main isolate 和 spawned isolate(由 spawn 建立的 isolate)無法直接通訊。實際上,即使您不需要從 spawned isolate 返回任何計算結果,您仍然需要某種驗證來確認計算成功,因此您總是需要返回一條訊息。

為了啟用通訊,您必須設定埠。在調用 spawn 之前,您需要建立一個 ReceivePort 物件。ReceivePort 物件的 sendPort 成員作為 spawn 的另一個參數傳遞給 spawned isolate。

這意味著您傳遞給 spawn 的函數必須 專門 配置為使用該 sendPort 執行某些操作。換句話說,您不能僅將現有函數與 isolate 一起使用。因此,您不要將僅讀取和解析 JSON 檔案的常規函數傳遞給 spawn,而是建立如下內容:

您的專用、isolate 友好型 JSON 解碼函數可以簡單地「返回結果」,然後就完成了,對嗎?不完全是。結果需要透過 responsePort 傳送。這就是 isolate 與埠通訊的方式。您可以使用另一個基本元素 Isolate.exit() 來有效地返回結果並同時關閉 spawned isolate:

1
Isolate.exit(responsePort, result);

exit() 函數將儲存 spawned isolate 中訊息的記憶體 傳輸 到 main isolate(而不是複製它),並安全地關閉 isolate。

讓我們把這些都串在一起。由於此範例中的 result 是解析的 JSON,您可能想要稍微解構它才能實際使用它。為了程式碼的簡潔性,我們應該將建立 receivePort 和 isolate 並等待它們的回應的三行程式碼放在它們自己的函數中,而不是直接放在 main() 中。

正在完成的工作相對簡單。正是實作細節的暴露讓它 感覺 起來很複雜,例如用於訊息傳遞的埠,以及需要一個專用函數來處理埠,而該函數與 isolate 無關。

錯誤處理

到目前為止的範例 仍然 不是一個真正的「完整」、可投入生產的實作。如果您不做任何錯誤處理,那將對您自己不利,但它通常在已經相當多的流程中被遺忘為一個額外的步驟。例如,如果沒有任何錯誤處理,未捕獲的異步錯誤導致 isolate 崩潰,您將不知道導致錯誤的原因,甚至不知道 發生了什麼事

涵蓋 isolate 的所有錯誤處理可能性將會很廣泛,但通常需要對程式碼進行一些額外的補充。

您至少可以將 errorsAreFatalonExitonError 參數加入到 spawn 調用中:

這可以確保即使 spawned isolate 在沒有傳送結果的情況下終止,或者發生任何未捕獲的錯誤,resultPort 都會收到一條訊息。將錯誤設定為致命意味著未捕獲的錯誤會退出 isolate 作為安全預防措施,以確保它一定會終止。

onExit 參數使 isolate 在退出時向埠傳送 nullonError 參數使未捕獲的錯誤向埠傳送兩個字串的列表(錯誤和堆疊追蹤的 toString)。

重複使用結果埠可以避免建立更多埠,因此您只需在一个地方查找訊息。但這也意味著您需要區分 onExitonError 訊息與結果值。在這裡,我們假設 JSON 必須是一個 Map,因此它不能是列表或 null。否則,您還必須將結果包裝在可以識別的內容中。您必須在埠訊息之上建立一個(微不足道的)訊息協定。

除此之外,您還可以檢查回應中的特定錯誤。其中一種情況是檢查 resultPort 是否為 null,這意味著 isolate 在沒有傳送結果的情況下終止:

另一種情況是檢查結果是否為列表,這意味著發生了未捕獲的錯誤:

然後,最後,處理實際的結果:

無論如何,您都希望將 spawn 放在 try 塊中,以檢查將入口點傳送到新的 isolate 是否失敗。如果失敗了,結果埠將不會收到任何訊息,並且需要關閉:

提供最基本的錯誤處理可以確保結果埠始終關閉,並且 *spawnAndReceieve 始終完成,無論 spawned isolate 如何退出。您還可以做得 更好,例如,透過捕獲錯誤和堆疊追蹤並將它們作為實際物件傳送回去,而不僅僅是像 onError 處理程式那樣的字串。

錯誤處理顯然會引入很多變化,以及決定如何處理它以及要考慮哪些因素的心理開銷。可以理解的是,它通常被忽略在基本 isolate 設定之外。

使用 Isolate(之後)

Isolate.run() 使用您以前必須自己使用的基本元素,在單個函數調用中設定 isolate 實作的所有部分:

沒有埠、沒有單獨的生成、退出或錯誤處理,也沒有特殊的返回結構。也許最好的部分是,您傳遞給 run 的入口點可以是任何現有函數:

此範例顯示了一個 異步 函數,但 run 可以同樣輕鬆地執行 同步 函數。run 函數本身始終異步返回,這才是最重要的。

入口點也可以是 函數表達式,直接在您調用 run 的位置內聯編寫。Isolate 和在其上編寫的任何更高級別的 API 不再局限於僅運行靜態或頂級函數。

不再需要額外的訊息參數,您可以避免在列表等資料結構中打包和解包參數。

您根本不需要考慮太多錯誤處理。run 函數結合了本地和遠端錯誤捕獲、處理和跨 isolate 通訊,並將結果公開為單個普通的(異步)錯誤,您可以在標準的 try/catch 中捕獲它。您可以忘記 isolate,並將其視為普通的函數。

Isolate.run() 可以讓程式碼更加簡潔和符合人體工程學。Flutter 的 compute 函數甚至也轉而使用 run 而不是 spawn

Isolate.run() 內部

看看 run 的實作。它深入研究了所有與 isolate 相關的低階 API(這在以前是您的工作),以構建一個「完美」、全面的 isolate 設定。它接受要執行的 computation 方法,並設定所有埠及其返回值,以考慮 isolate 之間的有效訊息傳遞。

對每個潛在情況都進行了 徹底的 錯誤處理。run 函數會檢查 isolate 是否在完成計算之前就已終止。如果計算拋出錯誤,則 isolate 將終止,並將相同的錯誤拋出到 main isolate。

如果發生未捕獲的異步錯誤,則 isolate 將終止,並將錯誤異步報告給 main isolate。如果 main isolate 首先終止,則 spawned isolate 將終止,並將情況視為未捕獲的異步錯誤。

最後,run 總是使用 exit 來安全地關閉。這意味著資料可以有效地在 isolate 之間傳輸,而無需實際複製它。

總結

run 函數非常適合啟動一個計算並等待結果。如果您想為 run 未涵蓋的內容(例如可以多次傳送和接收訊息的 長時間運行的 isolate)建構自己的 isolate 設定,則基本元素仍然可用。但是,在大多數情況下,應該使用單個 run 語句替換 spawn 及其所有支援配置,而不是任何其他配置。

如果您在 run 之前從未嘗試過 isolate 管理,那麼很難相信所有這些功能以前都必須由使用者來實作!Isolate.run()(在 Dart 2.19 和 Flutter 3.7 中可用)使程式碼更加符合人體工程學,並使 isolate 更易於使用。您將如何利用 run 節省的時間呢?


使用 Isolate.run() 更好地管理 Isolate 最初發佈在 Medium 的 Dart 上,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章翻譯】What’s new in Flutter 3.7

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

Flutter 3.7 新功能:Material 3 更新、iOS 改進等等!

我們很高興在 2023 年開始時發佈 Flutter 3.7!在 Flutter 3.7 中,我們作為社群,繼續改進框架,加入了一些很棒的新功能,例如:建立自訂選單列、階層式選單、更好地支援國際化的工具、新的除錯工具等等。

我們還繼續完善一些功能,例如全局選取、透過 Impeller 進行更快渲染、DevTools,以及始終如一的效能!

讓我們一起踏上快速旅程,探索 Flutter 3.7 中的新功能吧!

增強的 Material 3 支援

Material 3 支援在 3.7 中得到了極大的增強,以下 Widget 已遷移:

若要使用這些新功能,只需在應用程式的 ThemeData Widget 中開啟 useMaterial3 旗標。若要充分利用 M3 支援,您需要完整的 M3 色彩方案。您可以自己提供,使用新的 主題建構工具,或者 Flutter 可以使用 ThemeData 建構函數的 colorSchemeSeed 參數從單個種子顏色為您生成一個:

1
2
3
4
5
6
7
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.green,
),
// …
);

有關 Flutter 的 Material 3 支援的最新資訊,請查看 GitHub 上的 總體議題

若要親自試用這些元件,請查看 互動式演示,展示了所有新的 M3 功能:

選單列和階層式選單

Flutter 現在可以建立選單列和階層式上下文選單。

對於 macOS,可以使用 PlatformMenuBar Widget 建立選單列,它定義由 macOS 而不是 Flutter 渲染的平台原生選單列。

而且,對於所有平台,您都可以定義一個 Material Design 選單,它提供階層式選單列 (MenuBar),或者由另一個使用者介面元素觸發的獨立階層式選單 (MenuAnchor)。這些選單完全可自訂,選單項目可以是自訂 Widget,或者您可以使用新的選單項目 Widget (MenuItemButtonSubmenuButton)。

Impeller 預覽

團隊很高興地宣布,新的 Impeller 渲染引擎 已在 stable channel 上的 iOS 上 準備好進行預覽。我們相信 Impeller 的效能對於大多數應用程式來說將會達到或超過 Skia 渲染器,至於保真度,Impeller 實作了所有功能,只有一些很少使用的角落案例除外。我們預計將在即將到來的穩定版本中將 Impeller 設為 iOS 上的預設渲染器,因此請在 GitHub 上繼續提交 Impeller 回饋

儘管我們越來越有信心 iOS 上的 Impeller 將滿足幾乎所有現有 Flutter 應用程式的渲染需求,但 API 涵蓋範圍仍然存在一些差距。在 Flutter wiki 上列出了少數幾個剩餘的差距。使用者也可能會注意到 Skia 和 Impeller 之間在渲染方面的細微視覺差異。這些細微的差異可能是錯誤,因此請勿猶豫 提交議題

社群的貢獻極大地加速了我們在 Impeller 上的進展。特別是 GitHub 使用者 ColdPaleLightguoguo338JsouLiangmagicianA 為此版本貢獻了 291 個(>12%)與 Impeller 相關的修補程式中的 37 個。謝謝!

我們繼續在 Impeller 的 Vulkan 後端上取得進展(在較舊的設備上回退到 OpenGL),但 Android 上的 Impeller 尚未準備好進行預覽。Android 支援正在積極開發中,我們希望在將來的版本中分享更多相關資訊,包括更多關於桌面和 Web 支援的資訊。

在 GitHub 上的 Impeller 專案看板 上關注我們的進展。

iOS 版本驗證

當您發佈 iOS 應用程式時,更新設定的清單 可以確保您的應用程式已準備好提交到 App Store。

flutter build ipa 命令現在會驗證其中一些設定,並在發佈之前通知您是否需要對應用程式進行更改。

DevTools 更新

在此版本中,有幾個新的工具功能和整體改進可以嘗試。DevTools 記憶體除錯工具已徹底改版。有三個新的功能標籤,剖析追蹤差異,它們支援所有以前支援的記憶體除錯功能,並為您的除錯工作添加了更多功能。新功能包括能夠按類別和記憶體類型分析應用程式目前的記憶體配置、調查在運行時哪些程式碼路徑正在為一組類別配置記憶體,以及比較記憶體快照以了解兩個時間點之間的記憶體管理。

所有這些新的記憶體功能都已記錄在 docs.flutter.dev 上,因此請查看文件以獲取更多資訊。

效能頁面也有一些值得注意的新功能。效能頁面頂部的一個新的 畫面分析 標籤提供了所選 Flutter 畫面的洞察力。洞察力可能包括如何更詳細地追蹤 Flutter 畫面中昂貴部分的建議,或者有關在 Flutter 畫面中檢測到的昂貴操作的警告。

這只是幾個亮點,但此版本包含若干錯誤修復和改進,超出此處提到的功能,包括針對 Inspector、網路分析工具和 CPU 分析工具的一些重要錯誤修復。若要更深入地了解更新列表,請查看 DevTools 變更的發行備註,這些變更已加入 Flutter 3.7。

自訂上下文選單

您現在可以在 Flutter 應用程式中的任何位置建立自訂上下文選單。您也可以使用它們自訂內建的上下文選單。

例如,您可以將「發送電子郵件」按鈕加入到使用者選取電子郵件地址時出現的預設文字選取工具列中 (程式碼)。查看 contextMenuBuilder 參數,該參數已加入預設顯示上下文選單的現有 Widget 中,例如 TextField。您可以從 contextMenuBuilder 返回任何您想要的 Widget,包括修改預設的平台自適應上下文選單。

此新功能也適用於文字選取之外。例如,您可以建立一個 Image Widget,當右鍵點擊或長按時顯示「儲存」按鈕 (程式碼)。使用 ContextMenuController 在應用程式中的任何位置顯示目前平台的預設上下文選單或自訂上下文選單。

Flutter 的樣本儲存庫 中查看完整的範例套件。

CupertinoListSection 和 CupertinoListTile Widget

感謝 Github 使用者 Campovski 的努力,Cupertino 有兩個新的 Widget:CupertinoListSectionCupertinoListTile,用於以 iOS 風格顯示可捲軸的 Widget 列表。它們是 Material 中 ListViewListTile 的 Cupertino 版本。

捲軸改進

這個版本包含了一些 捲軸更新:針對觸控板互動的潤色和完善、新的 Widget(例如 ScrollbarsDraggableScrollableSheet),以及改進了在捲軸上下文中選取文字的處理方式。

值得注意的是,MacOS 應用程式現在將會在新增 新的捲軸物理 以匹配桌面平台後,體驗到更高的保真度。

新的 AnimatedGridSliverAnimatedGrid Widget 會為加入(或移除)列表的項目製作動畫。

最後,我們 修復了若干捲軸 Widget 的建構函數中的回歸,例如 ListView。在 Flutter 框架的 NNBD 遷移期間,itemBuilder(允許使用者按需提供 Widget)被遷移到 IndexedWidgetBuilder。這意味著 itemBuilder 不再可以返回 null,而 null(在過去)可以用於表示已到達列表的末尾。此功能已透過 NullableIndexedWidgetBuilder 恢復。感謝 @rrousselGit 注意到這一點——遷移幾年後——並發送了修復程式!

國際化工具和文件

國際化支援已完全改版!我們已完全重寫 gen-l10n 工具,以支援:

  • 描述性語法錯誤。
  • 包含巢狀/多個複數、選擇和佔位符的複雜訊息。

有關更多資訊,請查看更新後的 國際化 Flutter 應用程式 頁面。

全局選取改進

SelectionArea 現在支援鍵盤選取。您可以使用鍵盤快捷鍵(例如 shift+right)擴展現有選取範圍。

背景隔離區

現在,平台通道 可以從任何 隔離區 呼叫。以前,使用者只能從 Flutter 提供的主要隔離區呼叫平台通道。這使得在 PluginAdd-to-app 中使用隔離區和主機平台程式碼變得更好。有關更多資訊,請查看 flutter.dev 上的 撰寫自訂平台特定程式碼 以及深入文章 簡介背景隔離區通道,這是一篇免費的 Medium 文章。

文字放大鏡

在 Android 和 iOS 上文字選取期間出現的放大鏡現在可以在 Flutter 中使用。這對於所有具有文字選取的應用程式來說都是開箱即用的,但如果想停用或自訂它,請查看 magnifierConfiguration 屬性。

Plugin 的 Swift 遷移

隨著 Apple 將重點放在他們自己的 API 上的 Swift,我們希望開發一些參考來幫助 Flutter Plugin 開發人員使用 Swift 遷移或建立新的 Plugin。quick_actions Plugin 已從 Objective-C 遷移到 Swift,可以用作最佳實務的演示。如果您有興趣幫助我們遷移 1P Plugin,請查看 wiki 的 Swift 遷移部分

面向 iOS 開發人員的資源

我們為 iOS 開發人員發佈了一些新的資源,包括:

Bitcode 棄用

從 Xcode 14 開始,watchOS 和 tvOS 應用程式不再需要 Bitcode,App Store 不再接受來自 Xcode 14 的 Bitcode 提交。 因此,Bitcode 支援已從 Flutter 中移除。

預設情況下,Flutter 應用程式沒有啟用 Bitcode,我們預計這不會影響太多開發人員。但是,如果您在 Xcode 專案中手動啟用了 Bitcode,請在升級到 Xcode 14 後立即停用它。您可以透過打開 ios/Runner.xcworkspace 並將 啟用 Bitcode 設為 來執行此操作。 Add-to-app 開發人員應在主機 Xcode 專案中停用它。

若要進一步了解 Bitcode 分發,請查看 Apple 的文件

iOS PlatformView BackdropFilter

我們已添加了原生 iOS 視圖在渲染到模糊的 Flutter Widget 之下時被模糊的功能,並且 UiKitView Widget 現在可以包裝在 BackdropFilter 中。

有關更多資訊,請查看 iOS PlatformView BackdropFilter 設計文件。

記憶體管理

此版本對記憶體管理進行了一些改進,這些改進的共同效果是減少由垃圾收集暫停造成的卡頓,降低因配置速度和背景 GC 線程造成的 CPU 使用率,以及減小記憶體佔用空間。

例如,我們擴展了現有 的手動釋放支援某些 dart:ui Dart 物件的原生資源的做法。以前,原生資源將由 Flutter 引擎保留,直到 Dart VM 垃圾收集 Dart 物件。透過對使用者應用程式和我們自己的基準測試進行分析,我們確定這種策略通常不足以避免不合時宜的 GC 並過度使用記憶體。因此,在此版本中,Flutter 引擎添加了用於明確釋放 VerticesParagraphImageShader 物件持有的原生資源的 API。

在我們對遷移到此 API 的 Flutter 框架進行基準測試時,這些改進將 90% 的畫面建立時間縮短了 30% 以上,最終使用者將體驗到更平滑的動畫,卡頓更少。

此外,Flutter 引擎 不再註冊 GPU 圖片的大小到 Dart VM。如上所述,這些圖片在不再需要時已由框架手動釋放,因此通知 Dart 的 GC 策略支援 Dart 堆物件的 GPU 記憶體大小會不必要地增加 Dart 堆記憶體壓力,從而觸發無法收集任何額外記憶體的不合時宜的 GC。基於類似的思路,Flutter 引擎現在的策略是僅向 Dart VM 報告支援 dart:ui Dart 物件的原生物件的淺層大小

在我們的基準測試中,此變更在建立畫面時會消除同步 GC 工作,當時 Widget 會建立 GPU 常駐圖片。

在此版本中,Flutter 引擎也更好地動態更新 Dart VM,提供有關 Flutter 應用程式狀態的資訊。特別是,Flutter 現在使用 Dart VM 的 RAIL 風格 API 在路由轉場動畫期間進入 低延遲模式。在此低延遲模式下,Dart VM 的記憶體配置器優先選擇堆增長而不是垃圾收集,以避免使用 GC 暫停中斷轉場動畫。雖然此變更沒有帶來任何顯著的效能改善,但我們計劃在將來的版本中擴展此模型的使用範圍,以進一步消除不合時宜的 GC 暫停。此外,我們已 修復了邏輯中的錯誤,這些邏輯決定何時通知 Dart VM Flutter 引擎處於空閒狀態。修復這些錯誤還可以防止 GC 相關的卡頓。最後,對於 Add-to-app Flutter 應用程式,Flutter 引擎現在會 通知 Dart VM Flutter 視圖不再顯示。這現在導致 Dart VM 為與視圖關聯的隔離區觸發最終的重大 GC。此變更在沒有 Flutter 視圖可見時會減少 Flutter 的記憶體佔用空間。

停止支援 macOS 10.11 到 10.13

先前宣布,Flutter 不再支援 macOS 版本 10.11 和 10.12。自那次宣布以來,進一步的分析 顯示,移除對 10.13 的支援也會產生有限的額外影響,並且將有助於團隊大幅簡化程式碼庫。這意味著使用此版本及更高版本建立的針對穩定 Flutter SDK 的應用程式將不再在這些版本上運行,並且 Flutter 支援的最低 macOS 版本將升級到 10.14 Mojave。

因此,由於 Flutter 支援的所有 iOS 和 macOS 版本都包含 Metal 支援,因此 OpenGL 後端已從 iOS 和 macOS 嵌入器中移除。移除這些後端使 Flutter 引擎的壓縮大小減少了約 100KB。

toImageSync

此版本 添加了方法 Picture.toImageSyncScene.toImageSyncdart:ui 中,類似於異步方法 Picture.toImageScene.toImagePicture.toImageSync 同步返回一個 Image 的句柄,其中 Image 的光柵化會在背景中異步執行。然後,當 GPU 上下文可用時,圖片會保留為 GPU 常駐,這意味著與透過 toImage 生成的圖片相比,它的繪製速度更快。(透過 toImage 生成的圖片也可以保留為 GPU 常駐,但這種優化尚未在這種情況下實作。)

新的 toImageSync API 支援以下用例:

  • 迅速捕捉一個光柵化代價高昂的圖片,以便在多個畫面中重複使用。
  • 將多通道濾鏡應用於圖片。
  • 應用自訂著色器。

例如,Flutter 框架現在 使用此 API 來改進 Android 上的頁面轉場效能,這幾乎將畫面光柵化時間減半,減少了卡頓,並允許動畫在支援這些更新率的設備上達到 90/120fps。

自訂著色器支援改進

此版本包含 Flutter 對自訂片段著色器支援的許多改進。Flutter SDK 現在包含一個著色器編譯器,它會將 pubspec.yaml 檔案中列出的 GLSL 著色器編譯為目標平台的正確後端特定格式。此外,自訂著色器現在可以熱重新載入,以實現便捷的開發週期。自訂著色器現在也受 iOS 上的 Skia 和 Impeller 後端支援。

我們對社群已經分享的演示非常印象深刻,並且期待看到自訂著色器在 Flutter 中的進一步創新使用:

在 docs.flutter.dev 上查看 撰寫和使用自訂片段著色器 的詳細文件,並查看 pub.dev 上的實用程式套件 flutter_shaders

字體資產熱重新載入

以前,將新字體添加到 pubspec.yaml 檔案中需要重新建立應用程式才能看到它們,這與可以熱重新載入的其他資產類型不同。現在,對字體清單的更改(包括新增新字體)可以在應用程式中熱重新載入。

減少 iOS 設備上的動畫卡頓

感謝 luckysmg 的開源貢獻,兩個改進減少了 iOS 上的動畫卡頓。特別是,在手勢期間在主線程上添加一個虛擬 CADisplayLink 現在會強制以最大更新率刷新。此外,鍵盤動畫 現在會將 CADisplayLink 的更新率設定為與 Flutter 引擎的動畫器使用的相同更新率。由於這些更改,使用者應該會注意到 120Hz iOS 設備上更一致的平滑動畫。

總結

毫不誇張地說,沒有才華橫溢且充滿熱情的貢獻者社群,Flutter 就無法成為今天的傑出體驗。我們將繼續一起踏上這段旅程,Google 的 Flutter 團隊希望大家知道,沒有你們,我們是無法做到的。謝謝!

這股勢頭不會減弱,敬請關注未來的更新!


Flutter 3.7 的新功能 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。