0%

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

宣布 Dart 3.5 以及 Dart 路線圖更新

是時候發布我們另一個季度性的 Dart SDK 版本了。我們在互操作性方面有所改進,在 pub.dev 套件管理器中增加了新功能,並且將新的 Web 整合 API 提升到穩定版本 1.0。

我們的大部分時間都致力於更大的、跨越多個季度的項目,因此我們也對 Dart 路線圖進行了更新,詳細說明了我們希望在未來幾個季度取得進展的目標。

Dart 3.5 發布圖像。

Dart 3.5 中的新功能

Dart 3.5 包含許多下面討論的新功能。核心函式庫 API 也有一些較小的變更,以及大約 10 個非常小的重大變更,這些都在 變更日誌 中說明 。

Web 平台和 JS 互操作性

在 Dart 3.4 和 Flutter 3.22 中,我們引入了對 將 Flutter Web 應用程式編譯到 WebAssembly 的支援。編譯到 WebAssembly 需要使用我們新的 Dart 到 JS 互操作模型,該模型之前處於預覽狀態。從 Dart 3.5 開始,它現在被視為穩定且完整,我們已將 package:web(它取代了舊的 dart:html 函式庫)中的瀏覽器 API 綁定更新到版本 1.0。

我們鼓勵所有 Web 套件作者 遷移到 package:web。我們計劃在我們的下一個 Dart 版本中棄用舊的互操作 API(dart:html、dart:js、package:js 等),並在明年晚些時候完全停用它們。我們邀請您在 追蹤議題 中提供您對此計劃的回饋。我們還計劃更新 pub.dev 套件管理器的 評分,為支援新互操作模型的 Web 套件頒發積分。

我們還增加了一個 新的 Lint,它驗證您的程式碼是否正確使用了新的 JS 互操作類型。我們建議您將此 Lint 加入到您的 analysis_options.yaml 檔案中,作為遷移您的 Web 套件的一部分。

Dart 原生互操作性

我們還對原生互操作性進行了一系列改進,這些改進支援從 Dart 直接調用 C、Java、Kotlin、Objective-C 和 Swift。

C 互操作性由我們的 FFI(外部函數介面)函式庫啟用,我們已經支援了幾年。在 Dart 3.5 中,我們進行了增量改進,以支援將指標從 Dart TypedData 物件直接傳遞到 FFI,避免需要先將記憶體從 Dart 複製到原生(詳細資訊)。

Java 和 Kotlin 互操作性由 JNIgen 生成器(目前處於預覽狀態)啟用,它自動建立綁定程式碼,以便透過 Java 原生介面(JNI)從 Dart 調用 Java 和 Kotlin。我們改進了效能,並增加了對 Java 異常和 Kotlin 頂級函式的支援。我們還停用了以前的 基於 C 的綁定,因為替代的僅 Dart 綁定現在具有相當的效能和功能,並且更易於使用。如需詳細資訊,請查看 變更日誌

Objective-C 互操作性建立在 FFI 和我們的 FFIgen 生成器(目前處於預覽狀態)的基礎之上。我們增加了對 Objective-C 協定的支援,以及 NSString 等常見類型。如需使用 FFIgen 建立的套件的一個大型範例,請查看 cupertino_http,它與 Apple 的 URL 載入系統網路函式庫進行互操作。

在未來的版本中,我們將繼續投資於進一步的互操作性 - 既包括完成上述函式庫,也包括支援 Swift。請參閱下面的路線圖部分以獲取詳細資訊。

pub.dev 套件儲存庫

pub.dev 是我們的套件儲存庫,社群可以在其中分享和查找具有豐富功能的套件。我們在此處進行了一些改進。首先,我們改進了對 主題 的支援:套件作者可以使用此機制使用套件所屬的類別(例如 Widget)對其套件進行標記。我們現在 彙整 涵蓋相同類別但使用略微不同的措辭的常見主題(例如 Widget 與 Widget)。

其次,我們新增了一個新的 pub unpack 命令。這提供了一種在檔案系統中快速下載套件的簡單方法。例如,如果您要運行套件的範例程式並在您的本地機器上運行程式,則可以使用它:

1
2
3
4
5
6
7
8
$ dart pub unpack path
Downloading path 1.9.0 to `./path-1.9.0`...

$ cd path-1.9.0/example/

$ dart run example.dart
Current path style: posix
Current process path: /Users/mit/tmp/path-1.9.0/example

第三,我們新增了一個新的 pub downgrade –tighten 命令。這可以用於檢查套件相依關聯中的所有版本約束。運行時,它會將下限約束更新到 pub 成功進行解析的最低版本。

Dart 路線圖更新

除了上述已完成的功能外,我們還在許多領域進行了工作,以使我們的長期路線圖取得進展。

大型 Monorepo 的 IDE 和分析器效能

「Monorepo」是對一組相關套件和應用程式進行建構的常見方式,將所有程式碼都放在同一個儲存庫中,例如 Flutter 的 套件儲存庫。Monorepo 不僅僅是將所有程式碼「放在一起」的便利性,而且還是確保儲存庫中單獨的套件和應用程式相互相容的關鍵工具。

我們從在大型 Monorepo 中工作的開發人員那裡收到了持續的回饋,表示我們的工具(特別是分析器)的效能可能存在缺陷。我們對這些問題的分析表明,根本問題在於我們最終會為每個套件及其 所有 相依關聯載入多個重疊的分析內容,導致儲存庫中每個套件的多次分析同時在記憶體中。我們認為根本的解決方案是在此類儲存庫中建立每個相依關聯版本的單一、共用解析,並且正在透過一個稱為 工作區 的新 pub 功能來實現此功能。我們將在下一個 Dart 版本中分享更多關於此功能的資訊,但現在您可以先看看它是如何 最近應用於 Flutter 引擎儲存庫的

pub.dev 套件儲存庫

pub.dev 套件儲存庫的使用者長期以來一直要求改進 每個套件的使用次數/下載次數 指標。這對於套件作者來說很有幫助,可以作為他們的工作產生多少使用者效益的信號,對於套件使用者來說也有幫助,可以作為其他開發人員在使用哪些套件的信號。我們很高興地分享我們在這個功能方面取得了良好的進展,並且希望在年底前提供預覽版本。

Dart 原生互操作性

對於使用 JNIgen 的 Java 和 Kotlin 互操作性,我們預計在未來的兩個季度內完成核心支援,並從實驗性版本升級到穩定版本 1.0。如需詳細資訊,請參閱 JNIgen 追蹤器。對於 ObjectiveC 互操作性,我們也有類似的目標;請參閱 Objective-C 追蹤器

接下來,我們將調查與 Swift 程式碼的直接互操作性。初步實驗看起來很有前景,我們希望在明年年初新增實驗性支援。

原生互操作性和原生原始碼的捆綁

在許多情況下,直接互操作性用於調用存在於作業系統中的 API,這意味著這些 API 始終在這些主機平台上可用。但是,在某些情況下,Dart 正在與其進行互操作的程式碼是原生 原始碼,而不是直接包含在主機上,這對使用此互操作性的套件作者來說是一個實際挑戰:如何將這些原生原始碼捆綁和構建,而無需將大量手動步驟推送到套件的使用者?為了支援這一點,我們正在探索一個 原生資產系統,它可以支援發佈包含原生原始碼的 Dart 套件,以及一個標準化協定,允許 dart 和 flutter CLI 工具自動化這些原始碼的構建和捆綁。我們設想這將啟用一組新的互操作性用例,同時為使用依賴於原生原始碼的套件的開發人員提供簡化的使用者體驗。

Dart 語言和宏

Dart 語言和編譯器團隊目前的大部分時間都花在了非常大型的語言功能宏的進展上,我們在 Dart 3.4 部落格文章 中介紹了這個功能。正如我們當時所說,這是一項巨大的工作,有可能會導致我們的一些核心用例(例如熱重載)出現回歸,因此我們正在採取徹底的方法,並且可能需要幾個季度的進一步工作才能分享下一步的詳細資訊。

除了宏之外,我們還同時探索了許多其他的較小的語言功能,如 Dart 語言漏斗 中所記錄的那樣。

從去年秋天開始,我們一直在重寫 Dart 格式化程式。舊的設計在過去的幾年裡運行良好,但是隨著 Flutter 的成功,我們希望遷移到 一種新的風格,以便更好地適應 Flutter 使用者經常編寫的聲明式程式碼類型。舊的格式化程式無法產生那種輸出。重寫工作即將完成,並且很快就會發佈。如果您想嘗試一下,請使用 experiment 標誌 tall-style(標誌說明)。如果您看到奇怪的輸出,歡迎您 提供回饋

結語

這就是我們今天要分享的內容。我們歡迎您提供回饋,無論是關於討論的路線圖項目,還是關於 Dart 3.5 中的新功能,這些功能可以在 Dart.dev 上獲得,或者捆綁在今天的 Flutter 3.24 版本 中。


宣布 Dart 3.5 以及 Dart 路線圖更新 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

undefined

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

在 Flutter 中建立自訂渲染器並渲染 3D 場景。

Flutter 3.24 版本引進了一個新的低階圖形 API,稱為 Flutter GPU。還有一個由 Flutter GPU 支援的 3D 渲染函式庫,稱為 Flutter Scene(套件:flutter_scene)。Flutter GPU 和 Flutter Scene 目前都處於預覽階段,僅在 Flutter 的 主頻道 上可用(由於依賴實驗性功能),需要 啟用 Impeller,並且可能偶爾會引入重大變更。

本文包含這兩個套件的兩個「入門」指南:

  1. 🔺 進階:使用 Flutter GPU 入門
    如果您是經驗豐富的圖形程式設計師,或者您對低階圖形感興趣,並想在 Flutter 中從頭開始建立渲染器,那麼本指南將幫助您開始使用 Flutter GPU。您將從頭開始繪製第一個三角形… 在 Flutter 中!
  2. 💚 中級:使用 Flutter Scene 進行 3D 渲染
    如果您是想要將 3D 功能添加到應用程式中的 Flutter 開發人員,或者您想要使用 Dart 和 Flutter 建立 3D 遊戲,那麼本指南適合您!您將設定一個專案,在 Flutter 中匯入和渲染 3D 資產。

使用 Flutter GPU 入門

⚠️ 警告!⚠️ Flutter GPU 最終是一個低階 API。絕大多數將從 Flutter GPU 的存在中受益的 Flutter 開發人員很可能會透過使用在 pub.dev 上發佈的更高階渲染函式庫來做到這一點,例如 Flutter Scene 渲染套件。如果您對 Flutter GPU API 本身不感興趣,而只是對 3D 渲染感興趣,請跳到 使用 Flutter Scene 進行 3D 渲染

哦,真閃亮。這是一個射線行進的符號距離場。您可以使用 Flutter GPU 渲染它,但使用 [自訂片段著色器](https://docs.flutter.dev/ui/design/graphics/fragment-shaders) 也完全有可能。

使用 Flutter GPU 入門

Flutter GPU 是 Flutter 內建的低階圖形 API。它允許您透過撰寫 Dart 程式碼和 GLSL 著色器在 Flutter 中建立和整合自訂渲染器。不需要原生平台程式碼。

目前,Flutter GPU 處於早期預覽階段,並提供基本的柵格化 API,但隨著 API 逐漸穩定,將會繼續新增和改進更多功能。

Flutter GPU 還需要 啟用 Impeller。這表示它只能在 Impeller 支援的平台上使用。在撰寫本文時,Impeller 支援:

  • iOS(預設啟用)
  • macOS(選擇性預覽)
  • Android(選擇性預覽)

我們對 Flutter GPU 的目標是最終支援所有 Flutter 的平台目標。最終目標是促進 Flutter 中跨平台渲染解決方案的生態系統,這些解決方案對於套件作者來說易於維護,對於使用者來說易於安裝。

3D 渲染只是一個可能的用例。Flutter GPU 也可以用於建立專用的 2D 渲染器,或者執行更非正統的操作,例如渲染 4D 空間的 3D 切片,或投影非歐幾里德空間。

由 Flutter GPU 支援的自訂 2D 渲染器的絕佳用例範例將是依賴骨骼網格變形的 2D 角色動畫格式。Spine 2D 就是一個很好的例子。這種骨骼網格解決方案通常具有動畫剪輯,這些剪輯會操縱層次結構中骨骼的平移、旋轉和縮放屬性,並且每個頂點都具有一些關聯的「骨骼權重」,這些權重決定哪些骨骼應該影響頂點,以及影響程度。

使用像 drawVertices 這樣的 Canvas 解決方案,需要在 CPU 上對每個頂點應用骨骼權重轉換。使用 Flutter GPU,骨骼轉換可以以統一陣列或甚至紋理取樣器的形式傳遞到頂點著色器,允許根據骨骼狀態和每個頂點的骨骼權重在 GPU 上並行計算每個頂點的最終位置。

說到此,讓我們透過一個溫和的介紹來開始使用 Flutter GPU:繪製您的第一個三角形!

將 Flutter GPU 加入您的專案

首先,請注意 Flutter GPU 目前處於早期預覽狀態,可能會發生 API 斷裂。目前 API 已經可以實現很多功能,但是有經驗的圖形工程師可能會注意到一些缺失的常見功能。Flutter GPU 在接下來的幾個月裡將會新增許多功能。

基於這些原因,強烈建議您在針對 Flutter GPU 開發套件時,暫時使用 主頻道 的頂端。如果您遇到任何意外行為、錯誤或有功能請求,請使用標準的 Flutter 問題範本 在 GitHub 上提交問題。與 Flutter GPU 相關的所有追蹤問題都標記為 flutter-gpu 標籤

因此,在試驗 Flutter GPU 之前,請透過執行以下命令將 Flutter 切換到 main channel。

1
2
flutter channel main
flutter upgrade

現在建立一個新的 Flutter 專案。

1
2
flutter create my_cool_renderer
cd my_cool_renderer

接下來,將 flutter_gpu SDK 套件加入到您的 pubspec 中。

1
flutter pub add flutter_gpu --sdk=flutter

建立和匯入著色器捆綁包。

為了使用 Flutter GPU 渲染任何東西,您需要撰寫一些 GLSL 著色器。Flutter GPU 的著色器與 Flutter 的 片段著色器 功能所使用的著色器具有不同的語義,特別是在統一繫結方面。您還需要定義一個頂點著色器,與片段著色器一起使用。

從定義最簡單的著色器開始。您可以將著色器放置在專案中的任何位置,但是對於此範例,請建立一個 shaders 目錄,並使用兩個著色器填充它:simple.vert 和 simple.frag。

1
2
3
4
5
6
7
// 複製到:shaders/simple.vert

in vec2 position;

void main() {
gl_Position = vec4(position, 0.0, 1.0);
}

在繪製三角形時,您將擁有一個定義每個頂點的資料列表。在本例中,它僅列出 2D 位置。對於這些頂點中的每一個,簡單的頂點著色器都會將這些 2D 位置分配給剪輯空間輸出內在 gl_Position。

1
2
3
4
5
6
7
// 複製到:shaders/simple.frag

out vec4 frag_color;

void main() {
frag_color = vec4(0, 1, 0, 1);
}

片段著色器甚至更簡單;它輸出一個 RGBA 顏色,範圍為 (0, 0, 0, 0) 到 (1, 1, 1, 1)。因此,所有內容都將被著色為綠色。

好的,現在您有了著色器,請使用 Flutter 的提前編譯 (AOT) 著色器編譯器將它們編譯。為了為著色器捆綁包設定自動化的建置,我們建議您使用 flutter_gpu_shaders 套件。

使用 pub 將 flutter_gpu_shaders 作為專案中的常規相依性加入。

1
flutter pub add flutter_gpu_shaders

Flutter GPU 著色器捆綁到 .shaderbundle 檔案中,可以作為常規資產添加到專案的資產捆綁包中。著色器捆綁包包含針對平台目標的編譯著色器來源。

接下來,建立一個著色器捆綁包宣告檔案,描述著色器捆綁包的內容。將以下內容添加到專案根目錄中的 my_renderer.shaderbundle.json。

1
2
3
4
5
6
7
8
9
10
{
"SimpleVertex": {
"type": "vertex",
"file": "shaders/simple.vert"
},
"SimpleFragment": {
"type": "fragment",
"file": "shaders/simple.frag"
}
}

著色器捆綁包中的每個條目都可以具有任意名稱。在本例中,名稱是「SimpleVertex」和「SimpleFragment」。這些名稱用於在您的應用程式中查找著色器。

接下來,使用 flutter_gpu_shaders 套件建置 shaderbundle。您可以透過啟用實驗性的「原生資產」功能來新增一個掛鉤,該掛鉤會自動觸發建置。使用以下命令來啟用原生資產並安裝 native_assets_cli 套件。

1
2
flutter config --enable-native-assets
flutter pub add native_assets_cli

啟用原生資產功能後,在掛鉤目錄下新增一個 build.dart 脚本,它將自動觸發建置著色器捆綁包。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 複製到:hook/build.dart

import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:flutter_gpu_shaders/build.dart';

void main(List<String> args) async {
await build(args, (config, output) async {
await buildShaderBundleJson(
buildConfig: config,
buildOutput: output,
manifestFileName: 'my_renderer.shaderbundle.json');
});
}

進行此更改後,當 Flutter 工具建置專案時,buildShaderBundleJson 將建置著色器捆綁包,並將結果輸出到套件根目錄下的 build/shaderbundles/my_renderer.shaderbundle。

著色器捆綁包格式本身與您使用的 Flutter 特定版本綁定,並且可能會隨著時間推移而改變。如果您正在撰寫一個建置著色器捆綁包的套件,請不要將生成的 .shaderbundle 檔案檢查到您的原始碼樹中。相反,請使用建置掛鉤來自動化建置流程(如前所述)。

這樣一來,使用您函式庫的開發人員將始終使用正確格式建置新的著色器捆綁包!

現在,您已經自動化了著色器捆綁包的建置,請像常規資產一樣匯入它。將資產條目添加到專案的 pubspec.yaml 中:

1
2
3
flutter:
assets:
- build/shaderbundles/

在未來,原生資產功能將允許建置掛鉤將資料資產附加到捆綁包中。一旦發生這種情況,就不需要再在建置掛鉤旁邊新增資 * * * * *產匯入規則了。

接下來,新增一些程式碼,在執行時載入著色器。建立 lib/shaders.dart 並新增以下程式碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 複製到:lib/shaders.dart

import 'package:flutter_gpu/gpu.dart' as gpu;

const String _kShaderBundlePath =
'build/shaderbundles/my_renderer.shaderbundle';
// 注意:如果您正在建立函式庫,則路徑必須以套件名稱為前綴
// 例如:
// 'packages/my_cool_renderer/build/shaderbundles/my_renderer.shaderbundle'

gpu.ShaderLibrary? _shaderLibrary;
gpu.ShaderLibrary get shaderLibrary {
if (_shaderLibrary != null) {
return _shaderLibrary!;
}
_shaderLibrary = gpu.ShaderLibrary.fromAsset(_kShaderBundlePath);
if (_shaderLibrary != null) {
return _shaderLibrary!;
}

throw Exception("Failed to load shader bundle! ($_kShaderBundlePath)");
}

此程式碼為 Flutter GPU 著色器執行時函式庫建立一個單例 getter。第一次訪問 shaderLibrary 時,會使用 gpu.ShaderLibrary.fromAsset(shader_bundle_path) 使用建置的資產捆綁包初始化執行時著色器函式庫。

專案現在已經設定好使用 Flutter GPU 著色器。是時候渲染那個三角形了!

绘制您的第一個三角形

對於本指南,您將建立一個 RGBA Flutter GPU 紋理和一個 RenderPass,將紋理作為顏色輸出附加到它。然後,您將使用 Canvas.drawImage 在 Widget 中渲染紋理。

為了簡潔起見,您將放棄最佳實務,只會為每一幀重新建置所有資源。

只要您在分配紋理時將其標記為「著色器可讀取」,您就可以將其轉換為 dart:ui.Image。若要將渲染結果顯示在 Widget 樹中,請將其繪製到 dart:ui.Canvas 上!

您可以透過使用自訂畫家為 Widget 樹架設腳手架來存取 Canvas。將 lib/main.dart 的內容替換為以下內容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_gpu/gpu.dart' as gpu;

// 注意:我們之前在設定著色器捆綁包匯入時建立了它!
import 'shaders.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter GPU Triangle Example',
home: CustomPaint(
painter: TrianglePainter(),
),
);
}
}

class TrianglePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// 嘗試存取 `gpu.gpuContext`。
// 如果 Flutter GPU 不受支援,將會拋出異常。
print('Default color format: ' +
gpu.gpuContext.defaultColorFormat.toString());
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

現在,執行應用程式。提醒一下,Flutter GPU 目前需要 啟用 Impeller。因此,您必須使用 Impeller 支援的平台。對於本指南,我將以 macOS 為目標。

1
flutter run -d macos --enable-impeller

如果 Flutter GPU 正常工作,那麼您應該會看到預設顏色格式被列印到主控台中。

1
flutter: Default color format: PixelFormat.b8g8r8a8UNormInt

如果 Impeller 未啟用,則在嘗試存取 gpu.gpuContext 時會拋出異常。

1
2
3
4
Exception: Flutter GPU requires the Impeller rendering backend to be enabled.

The relevant error-causing widget was:
CustomPaint

為了簡便起見,您只會從這裡開始修改 paint 方法。

首先,建立一個 Flutter GPU 紋理,清除它,然後透過將其繪製到 Canvas 上來顯示它。

建立一個與 Canvas 大小相同的紋理。必須選擇一個 StorageMode。在本例中,您將紋理標記為 devicePrivate,因為您將只使用從設備 (GPU) 存取紋理記憶體的指令。

1
2
final texture = gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate,
size.width.toInt(), size.height.toInt())!;

如果透過從主機 (CPU) 上傳資料來覆蓋紋理的資料,則使用 StorageMode.hostVisible

第三個可用的選項是 StorageMode.deviceTransient,它對於不需要超過單個 RenderPass 壽命的附件很有用(因此它們可以只存在於瓦片記憶體中,並且不需要由 VRAM 分配支援)。通常,深度/模板紋理符合此標準。

接下來,定義一個 RenderTarget。渲染目標包含一組「附件」,描述每個片段的記憶體佈局及其在 RenderPass 開始和結束時的設定/拆卸行為。

本質上,RenderTarget 是 RenderPass 的可重複使用描述器。

現在,定義一個非常簡單的 RenderTarget,它只包含一個顏色附件。

1
2
final renderTarget = gpu.RenderTarget.singleColor(
gpu.ColorAttachment(texture: texture, clearValue: Colors.lightBlue));

請注意,此程式碼將 clearValue 設定為淡藍色。每個附件都具有 LoadActionStoreAction,它們分別確定在傳遞的開始和結束時應該對附件的臨時瓦片記憶體執行什麼操作。

預設情況下,顏色附件被設定為 LoadAction.clear(它將瓦片記憶體初始化為給定的顏色)和 StoreAction.store(它將結果儲存到附加的紋理的 VRAM 分配中)。

現在,建立一個 CommandBuffer,使用前面的 RenderTarget 從其中產生一個 RenderPass,然後立即提交 CommandBuffer 以清除紋理。

1
2
3
4
final commandBuffer = gpu.gpuContext.createCommandBuffer();
final renderPass = commandBuffer.createRenderPass(renderTarget);
// ... 繪製調用將放在這裡!
commandBuffer.submit();

剩下的就是將初始化的紋理繪製到 Canvas 上!

1
2
final image = texture.asImage();
canvas.drawImage(image, Offset.zero, Paint());

現在您有了連接到螢幕顯示結果的 RenderPass,您就可以開始繪製三角形了。若要執行此操作,請設定以下內容:

  1. 從著色器建立的 RenderPipeline,以及
  2. 包含幾何形狀的 GPU 可存取緩衝區(三個頂點位置)。

建立 RenderPipeline 很容易。您只需將函式庫中的頂點和片段著色器組合在一起。

1
2
3
final vert = shaderLibrary['SimpleVertex']!;
final frag = shaderLibrary['SimpleFragment']!;
final pipeline = gpu.gpuContext.createRenderPipeline(vert, frag);

現在是幾何形狀。回想一下,「SimpleVertex」著色器只有一個輸入:in vec2 position。因此,若要繪製三個頂點,您需要三組兩個浮點數。

1
2
3
4
5
6
7
final vertices = Float32List.fromList([
-0.5, -0.5, // 第一個頂點
0.5, -0.5, // 第二個頂點
0.0, 0.5, // 第三個頂點
]);
final verticesDeviceBuffer = gpu.gpuContext
.createDeviceBufferWithCopy(ByteData.sublistView(vertices))!;

剩下的就是繫結新的資源,並呼叫 renderPass.draw() 以完成記錄繪製調用。

1
2
3
4
5
6
7
8
9
10
renderPass.bindPipeline(pipeline);

final verticesView = gpu.BufferView(
verticesDeviceBuffer,
offsetInBytes: 0,
lengthInBytes: verticesDeviceBuffer.sizeInBytes,
);
renderPass.bindVertexBuffer(verticesView, 3);

renderPass.draw();

如果您啟動應用程式,您現在應該會看到一個綠色的三角形!

太棒了,您使用 Flutter、Dart 和一點 GLSL 從頭開始建立了一個渲染器!

無論這是否是您第一次渲染三角形,或者您是經驗豐富的圖形專家,我都希望您能繼續使用 Flutter GPU,並查看我們正在開發的套件,例如 Flutter Scene。

在未來,我們希望發佈友好的初學者程式碼實驗室,深入探討 Flutter GPU 的預設行為和最佳實務。我們還沒討論頂點屬性佈局、紋理繫結、統一和對齊要求、管道混合、深度和模板附件、透視校正等等!

在那之前,我建議您探索 Flutter Scene 作為如何使用 Flutter GPU 的更全面的範例。

使用 Flutter Scene 進行 3D 渲染

Flutter Scene(套件 flutter_scene)是一個新的 3D 場景圖套件,由 Flutter GPU 支援,它使 Flutter 開發人員能夠匯入動畫 glTF 模型並渲染即時 3D 場景。

目的是提供一個套件,讓在 Flutter 中輕鬆建立互動式 3D 應用程式和遊戲。

該套件最初是作為一個 dart:ui 擴展,用於用 C++ 編寫的 3D 渲染器,並直接建置到 Flutter 的原生執行時中,但它已經使用更靈活的介面針對 Flutter GPU 重新撰寫。

與 Flutter GPU API 本身一樣,Flutter Scene 目前處於早期預覽狀態,需要 啟用 Impeller。Flutter Scene 通常與 Flutter GPU API 的重大變更保持同步,因此強烈建議您在試驗 Flutter Scene 時使用 主頻道

接下來,使用 Flutter Scene 建立一個應用程式!

設定 Flutter Scene 專案

由於強烈建議您針對 主頻道 使用 Flutter Scene,請從切換到主頻道開始。

1
2
flutter channel main
flutter upgrade

接下來,建立一個新的 Flutter 專案。

1
2
flutter create my_3d_app
cd my_3d_app

Flutter Scene 依靠實驗性的「原生資產」功能來自動化著色器的建置。您將在稍後使用原生資產來設定自動匯入 Flutter Scene 的 3D 模型。

使用以下命令啟用原生資產。

1
flutter config --enable-native-assets

最後,將 Flutter Scene 添加為專案相依性。

您還需要在與 Flutter Scene 的 API 互動時使用一些 vector_math 構造,因此也添加 vector_math 套件。

1
flutter pub add flutter_scene vector_math

接下來,匯入一個 3D 模型!

匯入 3D 模型

首先,您需要一個要渲染的 3D 模型。對於本指南,您將使用常見的 glTF 樣本資產: DamagedHelmet.glb。以下是它的樣子。

原始的 Damaged Helmet 模型由 theblueturtle_ 在 2016 年建立(授權: [CC BY-NC 4.0 國際](https://creativecommons.org/licenses/by-nc/4.0/legalcode))。轉換後的 glTF 版本由 ctxwing 在 2018 年建立(授權: [CC BY 4.0 國際](https://creativecommons.org/licenses/by/4.0/legalcode))。

您可以從 GitHub 上託管的 glTF 樣本資產儲存庫 中獲取它。將 DamagedHelmet.glb 放置在您的專案根目錄中。

1
curl -O https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/main/2.0/DamagedHelmet/glTF-Binary/DamagedHelmet.glb

像大多數即時 3D 渲染器一樣,Flutter Scene 在內部使用專用的 3D 模型格式。您可以使用 Flutter Scene 的離線匯入器工具將標準 glTF 二進制檔案(.glb 檔案)轉換為此格式。

將 flutter_scene_importer 套件作為常規相依性添加到專案中。

1
flutter pub add flutter_scene_importer

添加此套件可以使用 dart run 手動呼叫匯入器。

1
2
3
4
dart --enable-experiment=native-assets \
run flutter_scene_importer:import \
--input "path/to/my/source_model.glb" \
--output "path/to/my/imported_model.model"

您可以透過使用原生資產建置掛鉤來自動執行匯入器。若要執行此操作,請先將 native_assets_cli 作為常規專案相依性安裝。

1
flutter pub add native_assets_cli

現在您可以撰寫建置掛鉤了。使用以下內容建立 hook/build.dart。

1
2
3
4
5
6
7
8
9
10
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:flutter_scene_importer/build_hooks.dart';

void main(List<String> args) {
build(args, (config, output) async {
buildModels(buildConfig: config, inputFilePaths: [
'DamagedHelmet.glb',
]);
});
}

使用 flutter_scene_importer 中的 buildModels 公用程式,提供要建置的模型列表。路徑相對於專案的建置根目錄。

當 Flutter 工具建置專案時,buildModels 現在將建置著色器捆綁包,並將結果輸出到套件根目錄下的 build/models/DamagedModel.model。

匯入的模型格式本身與您使用的 Flutter Scene 特定版本綁定,並且會隨著時間推移而改變。在撰寫使用 Flutter Scene 的應用程式或函式庫時,請勿將生成的 .model 檔案檢查到您的原始碼樹中。相反,請使用建置掛鉤從您的原始模型中生成它們(如前所述)。

這樣一來,隨著時間推移升級 Flutter Scene 時,您將始終使用正確格式建置新的 .model 檔案!

接下來,像常規資產一樣匯入模型。將資產條目添加到專案的 pubspec.yaml 中。

1
2
3
flutter:
assets:
- build/models/

在未來,原生資產功能將允許建置掛鉤將資料資產附加到捆綁包中。一旦發生這種情況,就不需要再在建置掛鉤旁邊新增資產匯入規則了。

渲染 3D 場景

現在是應用程式的程式碼了。

首先,建立一個有狀態的 Widget,用於在多個幀中保留 Scene。

您將根據時間進行動畫處理,因此將 SingleTickerProviderStateMixin 添加到狀態,以及一個 elapsedSeconds 成員。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_scene/camera.dart';
import 'package:flutter_scene/node.dart';
import 'package:flutter_scene/scene.dart';
import 'package:vector_math/vector_math.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget{
const MyApp({super.key});

@override
MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
double elapsedSeconds = 0;
Scene scene = Scene();

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My 3D app',
home: Placeholder(),
);
}
}

執行應用程式作為冒煙測試,以確保沒有錯誤。請記住要 啟用 Impeller

1
flutter run -d macos --enable-impeller

在繼續之前,請為動畫設定計時器。覆蓋 MyAppState 中的 initState 以呼叫 createTicker。

1
2
3
4
5
6
7
8
9
10
@override
void initState() {
createTicker((elapsed) {
setState(() {
elapsedSeconds = elapsed.inMilliseconds.toDouble() / 1000;
});
}).start();

super.initState();
}

只要 Widget 可見,計時器回呼就會為每一幀被呼叫。呼叫 setState 會觸發此 Widget 在每一幀重建。

接下來,載入之前放置在專案中的 3D 模型,並將其添加到 Scene 中。

使用 Node.fromAsset 從資產捆綁包中載入模型。將以下程式碼放置在 initState 中。

1
2
3
4
Node.fromAsset('build/models/DamagedHelmet.model').then((model) {
model.name = 'Helmet';
scene.add(model);
});

Node.fromAsset 會異步地從資產捆綁包中反序列化模型,並在模型準備好添加到場景中時解析返回的 Future

現在,MyAppState.initState 應該如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@override
void initState() {
createTicker((elapsed) {
setState(() {
elapsedSeconds = elapsed.inMilliseconds.toDouble() / 1000;
});
}).start();

Node.fromAsset('build/models/DamagedHelmet.model').then((model) {
model.name = 'Helmet';
scene.add(model);
});

super.initState();
}

但是,您仍然沒有實際渲染 3D Scene!若要執行此操作,請使用 Scene.render,它需要 UI Canvas、Flutter Scene Camera 和一個大小。

存取 Canvas 的一種方法是建立一個 CustomPainter:

1
2
3
4
5
6
7
8
9
10
11
12
13
class ScenePainter extends CustomPainter {
ScenePainter({required this.scene, required this.camera});
Scene scene;
Camera camera;

@override
void paint(Canvas canvas, Size size) {
scene.render(camera, canvas, viewport: Offset.zero & size);
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

不要忘記將 shouldRepaint 覆蓋設置為返回 true,以便在每次重建發生時自訂畫家都會重新繪畫。

最後,將 CustomPainter 添加到源樹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@override
Widget build(BuildContext context) {
final painter = ScenePainter(
scene: scene,
camera: PerspectiveCamera(
position: Vector3(sin(elapsedSeconds) * 3, 2, cos(elapsedSeconds) * 3),
target: Vector3(0, 0, 0),
),
);

return MaterialApp(
title: 'My 3D app',
home: CustomPaint(painter: painter),
);
}

此程式碼指示相機沿著一個連續的圓圈移動,但始終面向原點。

最後,啟動應用程式!

1
flutter run -d macos --enable-impeller

以下是我們組合的完整源程式碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_scene/camera.dart';
import 'package:flutter_scene/node.dart';
import 'package:flutter_scene/scene.dart';
import 'package:vector_math/vector_math.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget {
const MyApp({super.key});

@override
MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
double elapsedSeconds = 0;
Scene scene = Scene();

@override
void initState() {
createTicker((elapsed) {
setState(() {
elapsedSeconds = elapsed.inMilliseconds.toDouble() / 1000;
});
}).start();

Node.fromAsset('build/models/DamagedHelmet.model').then((model) {
model.name = 'Helmet';
scene.add(model);
});

super.initState();
}

@override
Widget build(BuildContext context) {
final painter = ScenePainter(
scene: scene,
camera: PerspectiveCamera(
position: Vector3(sin(elapsedSeconds) * 3, 2, cos(elapsedSeconds) * 3),
target: Vector3(0, 0, 0),
),
);

return MaterialApp(
title: 'My 3D app',
home: CustomPaint(painter: painter),
);
}
}

class ScenePainter extends CustomPainter {
ScenePainter({required this.scene, required this.camera});
Scene scene;
Camera camera;

@override
void paint(Canvas canvas, Size size) {
scene.render(camera, canvas, viewport: Offset.zero & size);
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

Flutter 光明的未來

如果您能夠成功地遵循這些指南中的其中一個並讓它運行起來:太棒了,恭喜!

Flutter GPU 和 Flutter Scene 都非常年輕,平台支援有限。但我想總有一天,我們會懷念這些不起眼的開端。

隨著 Impeller 的推廣,Flutter 團隊完全掌控了渲染堆疊,因為我们需要針對 Flutter 的用例專門化渲染器。現在,我們正在開啟 Flutter 歷史上的一個新篇章。一個由您共同掌控渲染的篇章!

Flutter Scene 最初是 Impeller 中的 C++ 組件,與 2D Canvas 渲染器一起,帶有一個精簡的 dart:ui 擴展。在我構建它時,我已經意識到 Flutter Engine 不會是它的最終目的地。

3D 渲染器的架構決策海洋是廣闊

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

宣布 Flutter 3.24 和 Dart 3.5

今天,我們將揭曉 Flutter 3.24Dart 3.5,以及 I/O 2024 Connect 系列 的最後一站,該系列將在幾個小時內在中國舉行——中國是世界上最活躍的 Flutter 社群之一,這使得這個時刻變得格外特別。

Dash flies in and lands to the left of an outline of 3.24. She presses a button that fills the 3.24 in with Flutter blue.

我們在 5 月份的 Google I/O 上啟動了一系列 令人興奮的更新,包括將 WebAssembly 編譯支援升級到 stable channel,改進 Impeller,以及預覽 Dart macros 的未來。

Flutter 3.24 和 Dart 3.5 發佈版本在我們幫助您製作出色的高效能應用程式(這些應用程式可以透過單個共用程式碼庫到達行動、網頁和桌面上的使用者)的使命之上。它們包括對新的 Flutter GPU API 的早期預覽,對網頁上元素嵌入的改進,以及幾個針對那些想要為 iOS 生態系統構建的開發人員的令人興奮的更新,包括對 Swift Package Manager 的早期支援,以及對 Cupertino Widgets 的功能更新。

讓我們開始吧!

Impeller:為跨平台圖形效能樹立新標竿

從歷史上看,跨平台框架需要在視覺效果上做出妥協,因為它們依賴於底層平台提供的更高級別的抽象。Flutter 採用了不同的方法,它擁有自己的渲染層,可以在每台設備上提供硬體加速的圖形和流暢的效能。我們在 Impeller著色器 方面取得了重大進展,為圖形(如 3D)解鎖了令人興奮的新可能性。

我們很興奮地分享全新的 Flutter GPU API 的早期預覽,這是一個功能強大、低階的圖形 API,直接整合到 Flutter SDK 中。API 允許您定義自訂柵格管道,並將繪製調用直接提交到 GPU,從而可以建立專用的渲染器,例如 2D Canvas 的替代方案、3D 場景圖,甚至用於創造視覺上令人驚豔、高效能和沉浸式體驗的粒子系統,而無需使用通常引擎級別需要的容量。

3D animation of a sci-fi space helmet rendered in flutter_scene.

考慮到 API 的低階性,我們預計對於那些沒有大量圖形開發經驗的開發人員來說,會有一段學習曲線。這就是為什麼我們正在投資渲染套件,例如新的 flutter_scene 套件,它利用 Flutter GPU API 允許匯入動畫 glTF 模型並構造 3D 場景,使您能夠輕鬆地在 Flutter 和 Dart 中建立 3D 應用程式和遊戲,如下所示。

儘管 Flutter GPU API 提供了令人興奮的可能性,但它仍然處於早期預覽階段,我們可能會對 API 進行重大變更。我們建議在使用 Flutter GPU 時針對 Flutter 的主頻道進行開發。在部落格文章 Introducing Flutter GPU & Flutter Scene 中了解更多資訊。

為 iOS 和 macOS 打造 Flutter:讓為 Apple 生態系統交付美麗、快速的應用程式變得更加容易

我們的目標是讓您能夠構建出色的應用程式,這些應用程式感覺起來像原生應用程式,並能完美地執行。這項工作的一部分是優化效能,以及最大限度地提高 Flutter 與底層平台的相容性,包括存取 Apple 生態系統的全部功能。

在此版本中,我們引入了對 Swift Package Manager 的早期支援,解鎖了對蓬勃發展的 Swift 套件生態系統的存取,並使 Flutter 外掛能夠利用大量預先構建的功能來加速開發。一旦 Swift Package Manager (SPM) 被 Plugin 開發人員廣泛採用,它應該會簡化 Flutter 安裝過程本身,並降低新手的入門門檻,特別是那些不熟悉 iOS 生態系統的人。我們鼓勵 Plugin 作者 嘗試將 SPM 支援添加到您的外掛中,並提供您體驗的 回饋

接下來,我們希望讓您始終能夠滿足設計師的要求,並在 iOS 上提供高保真度的體驗。為了實現這一點,我們開始著手現代化和擴展 Cupertino Widget,解決了 Cupertino 中的 15 個問題,並在 Widget 目錄 中加入了 37 個缺少的 Cupertino Widget。

最後,我們為 Flutter macOS 應用程式添加了 platform_viewwebview 支援,允許將原生 macOS UI 組件無縫整合到您的 Flutter 應用程式中,以提供更完整、更完善的使用者體驗。

展望未來,我們很興奮能更多地投資於其他 Cupertino Widget 的保真度,與我們的生態系統一起推出 Swift Package Manager,並提供其他調查,讓整合和與 Apple 平台的互操作變得更加容易。

強調充滿活力的 Flutter 社群的全球影響力

我們還想感謝社群的貢獻,包括您的貢獻!這組版本包含來自 167 多位獨特貢獻者的近 1,500 次提交,其中包括 49 位 全新 貢獻者。我們深受 Flutter 社群持續的高水準活動、承諾和增長所鼓舞,包括積極構建框架的那些人。謝謝您!

我們共同努力的影響力正在世界各地展現出來,創造出數百萬人每天使用的令人難以置信的應用程式和體驗。例如,以下是 案例研究 的搶先看,展示了中國科技公司小米的團隊如何以及為什麼使用 Flutter 為該公司備受歡迎的新型電動汽車 小米 SU7 開發一個配套應用程式。

在世界各地出現的許多其他令人興奮的 Flutter 應用程式範例:

  • SNCF Connect,法國鐵路和歐洲最大的 Flutter 應用程式(擁有超過 150 個螢幕)的擁有者,與奧運會合作為 Flutter 應用程式交付了許多更新,使數百萬遊客能夠在奧運會期間穿梭於法國各地。
  • Wolt,DoorDash 國際的一部分,使用 Flutter 擴展到商家零售市場。
  • 惠而浦,一家擁有全球影響力的《財富》500 強公司,正在使用 Flutter 在巴西探索新的銷售管道。
  • Monta,一家丹麥的電動汽車充電生態系統初創公司,在短短 3 個月內使用 Flutter 將其第一個行動應用程式推向市場,後來又成功地將其 Web 應用程式移植到 Flutter。

總結

以上只是這些版本中 Flutter 和 Dart 的許多新功能和更新中的一小部分,您可以在 Flutter 3.24 技術部落格 文章和 Dart 3.5 部落格文章 中了解更多資訊。

展望未來,我們對 Flutter 的未來充滿期待。我們仍然致力於我們的使命,並且感謝您——無論是貢獻者、社群成員還是 Flutter 開發人員——成為這段非凡旅程的一部分。我們迫不及待想看看您接下來會建立什麼!


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

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

解鎖 Flutter GPU、多視圖嵌入等等

Flutter 3.24 on a blue background

歡迎來到最新的 Flutter 更新!Flutter 3.24 充滿了令人興奮的新功能和增強功能,可以提升您的應用程式開發體驗。此版本重點介紹了 Flutter GPU 的預覽版本,它可以在 Flutter 中直接啟用進階圖形和 3D 場景。Web 應用程式現在可以嵌入多個 Flutter 視圖,增強應用程式的多功能性。最後,我們加入了影片廣告支援,以幫助您最大限度地提高收入。

在過去的幾個月裡,Flutter 社群一直非常活躍,擁有 852 個框架提交和 615 個引擎提交。我們很興奮地歡迎 49 位新貢獻者,他們幫助實現了此版本。您的奉獻和熱情推動著 Flutter 的前進。

因此,深入了解 Flutter 社群帶給這個最新版本的最新功能和增強功能吧!

Flutter 架構

新的 Sliver

此版本加入了新的 Sliver,可以將它們組合在一起以實現動態 app bar 行為:

您可以使用這些新的 Sliver 來製作浮動、保持固定或在使用者捲軸時調整大小的標題。這些新的 Sliver 類似於現有的 SliverPersistentHeaderSliverAppBar Sliver,但具有更簡單的 API,可以組合在一起以實現更大的效果。

這些新的 Sliver 附帶了新的範例程式碼。例如,PinnedHeaderSliver 的 API 文件有一個範例,可以重新建立 iOS 設定應用程式 app bar 的效果:

Cupertino 函式庫中的更新

在此版本中,我們改進了 CupertinoActionSheet 的保真度。在動作表單的按鈕上滑動手指現在可以提供觸覺回饋。按鈕的字體大小和粗細現在與原生對應物相符。

我們還為 CupertinoButton 加入了新的焦點屬性,現在您可以自訂已停用的 CupertinoTextField 的顏色。

Cupertino 函式庫的更新正在進行中,請期待未來版本中的更多更新!

TreeView

two_dimensional_scrollables 套件發佈了 TreeView Widget,以及幾個用於建立高效能捲軸樹的配套類別,這些樹可以在樹增長時向所有方向捲軸。套件中包含的樣本應用程式也已更新,其中包含幾個使用 TableViewTreeView Widget 的全新範例。

TreeSliver 也被加入到框架中,用於在一維捲軸中建立樹。TreeViewTreeSliver API 符合,使您能夠輕鬆地在適合您的使用案例之間切換。

CarouselView

此版本包含了 Material Design carousel Widget:CarouselView。CarouselView 呈現「Uncontained」佈局:一個可捲軸的項目列表,這些項目會捲軸到 container 的邊緣,並且當開頭和末尾項目捲出視圖和捲入視圖時,它們可以動態調整大小。

Flutter CarouselView example

Widget提供更多功能

此版本包含將核心 Widget 邏輯從 Material 函式庫移動到 Widgets 函式庫中以便更廣泛使用,這些邏輯不是設計專用的。這包括:

  • Feedback Widget,它提供輕鬆存取設備上的觸覺和音訊回饋,以點擊回應、長按等手勢。
  • ToggleableStateMixinToggleablePainter,用於建立複選框、開關
    和單選按鈕等切換 Widget 的基本類別。

為 AnimationStatus 增強列舉功能

在社群成員 nate-thegrate 的出色 貢獻 中,增強的列舉功能被加入到 AnimationStatus 中,包括 getter:

  • isDismissed
  • isCompleted
  • isRunning
  • isForwardOrCompleted

其中一些 getter 已經存在於 Animation 子類別中,例如 AnimationControllerCurvedAnimation。現在,所有這些狀態 getter 都可以在 Animation 子類別中使用,除了 AnimationStatus 之外。最後,一個 toggle 方法被加入到 AnimationController 中,用於切換動畫的方向。

SelectionArea 中的更新

Flutter 的 SelectionArea 現在支援使用滑鼠進行三擊和在觸控設備上雙擊的更多原生手勢。預設情況下,SelectionAreaSelectableRegion Widget 使用這些新的手勢。

三擊

  • 三擊 + 拖動:擴展段落塊中的選取範圍。
  • 三擊:選取點擊位置的段落塊。

雙擊

  • 雙擊 + 拖動:擴展文字區塊中的選取範圍(支援原生 Android/Fuchsia/iOS 和 iOS 網頁)。
  • 雙擊:選取點擊位置的文字(支援原生 Android/Fuchsia/iOS 和 Android/Fuchsia 網頁)。

引擎

Impeller

改善效能和保真度

為了在即將到來的穩定版本中移除 iOS 上的 Impeller 選擇不使用設定,團隊一直在努力改進 Impeller 的效能和保真度。例如,針對文字渲染的一系列改進 大幅提高了 emoji 捲軸的效能,消除了捲軸大量 emoji 時的卡頓,這對 Impeller 的文字渲染能力來說是一項極好的壓力測試。

此外,透過 解決許多問題,我們也在此版本中大幅改進了 Impeller 文字渲染的保真度。特別是,文字粗細、間距和字距調整現在都與傳統渲染器的文字保真度相符。

Before (Note gaps instead of proper kerning, and lighter than intended font weight.)
After
Before (Note incorrect spacing, for example in “vergelijken”)
After

Android 預覽

在此版本中,我們將繼續在 Android 上預覽 Impeller。我們延長了預覽期,因為 Impeller 用於 Platform Views 的 API 在 Android 14 中的一個錯誤 導致出現困難。這個錯誤後來被 Android 團隊修補了,但是許多已部署的設備在可預見的將來將運行未修補的 Android 版本。解決這些問題意味著需要額外的 API 遷移,因此需要額外的穩定版本週期。出於謹慎和為了確保 Flutter 應用程式可以在盡可能廣泛的設備上運行,我們將推遲將 Impeller 作為預設渲染器,直到今年晚些時候的穩定版本發佈。

隨著 Android 上的 Impeller 預覽繼續在 3.24 穩定版本週期中進行,我們請求 Flutter 開發人員升級到最新的穩定版本,並在啟用 Impeller 時提交有關任何發現的不足的錯誤。在此階段的回饋對確保 Impeller 在 Android 上取得成功以及我們能夠在今年晚些時候的版本中自信地將其設為預設渲染器至關重要。Android 硬體生態系統比 iOS 生態系統更加多元。因此,關於 Impeller 最有用的回饋應包括有關發生問題的特定設備和 Android 版本的詳細資訊。

改進縮放圖片的預設值

在此版本中,圖片的預設 FilterQuality 已從 FilterQuality.low 變更為 FilterQuality.medium。當一個大型圖片比其目標矩形大很多時(這是一個常見的情況),FilterQuality.low 會導致圖片看起來更加「像素化」,並且渲染速度比 FilterQuality.medium 慢。未來,團隊還將探索更適合各種 FilterQuality 級別的新名稱。

Flutter GPU 預覽

Flutter 推出了對渲染功能的重大更新,即 Flutter GPU,可在主頻道上使用。此低階圖形 API 允許開發人員使用 Dart 程式碼和 GLSL 著色器建立自訂渲染器,而無需任何原生平台程式碼。

Flutter GPU 擴展了您可以在 Flutter 中直接渲染的內容,啟用進階圖形和 3D 場景。它需要 Impeller 渲染後端,目前在 iOS、macOS 和 Android 上支援。儘管處於早期預覽階段,但 Flutter GPU 的目標是最終支援所有 Flutter 平台。

API 允許完全控制渲染傳遞附件、頂點階段和資料上傳到 GPU。這種靈活性對於建立複雜的渲染解決方案至關重要,從 2D 角色動畫到複雜的 3D 場景。

開發人員可以透過切換到 main channel 並將 flutter_gpu 套件加入到他們的專案中來開始使用 Flutter GPU。接下來的幾個月將看到更多功能和穩定性方面的改進,更高階的渲染函式庫(如 flutter_scene)將簡化這些進階功能的使用。

若要深入了解 Flutter GPU,並了解如何在您的專案中利用它,請查看詳細的 Flutter GPU 部落格文章。無論您是建立遊戲還是複雜的圖形,Flutter 的全新 GPU 功能都讓它成為產品的強大選擇。

網頁

多視圖嵌入

Flutter Web 應用程式現在可以利用多視圖嵌入,讓開發人員可以將內容同時渲染到多個 HTML 元素中。此功能稱為「嵌入模式」或「多視圖」,為將 Flutter 視圖整合到現有的 Web 應用程式中提供了靈活性。

在多視圖模式下,Flutter Web 應用程式不會在啟動時立即渲染。相反,它會等到主機應用程式使用 addView 方法加入第一個「視圖」。主機應用程式可以動態加入或移除這些視圖,Flutter 會根據需要調整其 Widget。

若要啟用多視圖模式,請在 flutter_bootstrap.js 檔案中的 initializeEngine 方法中設定 multiViewEnabled: true。然後,可以從 JavaScript 管理視圖,將它們加入到指定的 HTML 元素中,並根據需要移除它們。每次加入和移除視圖都會觸發 Flutter 中的更新,允許動態內容渲染。

此功能對於將 Flutter 整合到需要多個獨立 Flutter 視圖的複雜 Web 應用程式中特別有用。它還支援每個視圖的自訂初始化資料,啟用個人化的設定和互動式體驗。

若要深入了解如何在 Flutter 網頁應用程式中實作多視圖嵌入,請查看 詳細的文件

變現

影片廣告變現支援

我們推出了一個新的 互動式媒體廣告 (IMA) Plugin,以支援 Flutter 行動應用程式中的串流影片廣告變現。新的 IMA Plugin 為 Flutter 應用程式提供了新的廣告變現機會,這些機會建立在現有的 Google 行動廣告 (GMA) Plugin 之上,該 Plugin 主要支援展示廣告格式。

串流影片廣告通常在影片內容播放之前(開頭廣告)、期間(中間廣告)或之後(結尾廣告)顯示給使用者。一些串流影片廣告也可以跳過。

Flutter IMA 的優點:

  • 在 Flutter 應用程式中無縫變現影片播放器內容。例如,當應用程式使用者點擊影片內容上的播放時,您現在可以實作 Flutter IMA Plugin 以首先向使用者顯示一個 15 秒的廣告,然後再開始播放影片內容。
  • 利用原生 IMA SDK 的相同優點,包括存取 Google 優質廣告需求和行業標準合規性(例如 IAB VAST)。

初始發佈版本目前支援 Android 和 iOS 平台上的開頭影片廣告。中間廣告支援將很快提供。我們鼓勵您開始在 Flutter 應用程式影片內容中探索新的 IMA Plugin。如果您在 GitHub 上遇到任何問題或疑慮,請告知我們。

資源:Plugin 指南範例應用程式Git 儲存庫

iOS

Swift Package Manager 初始支援

今天,Flutter 使用 CocoaPods 來管理原生 iOS 或 macOS 相依。

Flutter 3.24 加入了對 Swift Package Manager 的早期支援。這帶來了許多優點,包括:

  1. 存取 Swift 套件生態系統。Flutter Plugin 將能夠利用不斷發展的 Swift 套件 生態系統!
  2. 簡化 Flutter 安裝。Swift Package Manager 與 Xcode 捆綁在一起。未來,您將不再需要安裝 Ruby 和 CocoaPods 來為 Apple 平台使用 Flutter。

我們鼓勵 Plugin 作者 嘗試將 Swift Package Manager 支援加入到您的 Plugin 中,並提供您體驗的回饋。

如果您對 Flutter 對 Swift Package Manager 的支援有任何回饋,請 提交議題

生態系統

Shared Preferences 設定 Plugin 更新

我們已在 shared_preferences Plugin 中加入了兩個新的 API,SharedPreferencesAsync 和 SharedPreferencesWithCache。最重大的變化是 Android 實作使用 Preferences DataStore 而不是 Shared Preferences。

SharedPreferencesAsync 允許使用者直接調用平台以獲取設備上儲存的最新偏好設定,代價是異步和比使用快取版本稍微慢一些。這對於可以由其他系統或隔離區更新的偏好設定很有用,這些偏好設定會使快取過時。

SharedPreferencesWithCache 建立在 SharedPreferencesAsync 之上,允許使用者同步存取偏好設定的本地快取副本。這與舊的 API 相似,但現在可以透過不同的參數多次實例化。

這些新的 API 旨在將來替換目前的 SharedPreferences API。但是,這是生態系統中最常用的 Plugin 之一,我們知道生態系統需要時間才能轉換到新的 API。

Flutter 和 Dart 套件生態系統峰會歐洲 2024

作為 Fluttercon Europe 2024 的一部分,我們舉辦了首屆面對面 Flutter 和 Dart 套件生態系統峰會。這是繼我們於 2023 年 8 月舉辦的第一屆虛擬峰會之後。在此查看討論會的重點摘要。

我們很高興地宣布,下一屆峰會將於 2024 年 9 月 20 日在紐約市舉行的 Fluttercon USA 舉行!如果您是套件作者或貢獻者,並且將參加 Fluttercon USA 2024,請 註冊 以保留您的峰會席位。

峰會匯集了套件作者和維護者,進行了以下主題的 unconference-style 議程:

  • 議程 1 - 原生互操作的過去、現在和未來
  • 議程 2 - 可持續的套件維護模型
  • 議程 3 - 解決套件生態系統碎片化問題

我們相信峰會,特別是在更通用的 Flutter 和 Dart 活動的一部分時,是社群之間公開討論的有價值的平台,用於找出關鍵挑戰和集思廣益解決方案。我們期待與社群合作,在未來舉辦更多此類峰會。

DevTools 和 IDE

此版本包含一些對 Flutter DevTools 工具套件的令人興奮的改進。

如果您曾經想知道您的 Flutter 應用程式是否建立了比預期更多的 Widget,那麼 DevTools 效能 工具中的一個新功能可以幫助您。使用新的 重新建立統計資料 功能,您可以捕獲有關應用程式中或甚至特定 Flutter 畫面中 Widget 建立次數的資訊。

DevTools 效能工具的螢幕截圖,追蹤重新建立統計資料。

我們已為 網路分析工具Flutter Deep Links 工具 等工具加入了潤色和關鍵錯誤修復,並且進行了一些一般性改進,以在您從 IDE 中使用 DevTools 時為您提供更好的體驗。說到 IDE,您知道您可以在 IDE 中直接使用每個 DevTools 工具嗎?

DevTools 螢幕在 VS Code 視窗中打開。

DevTools 螢幕在 Android Studio 工具視窗中打開。

此版本包含對 VS Code 中的 Flutter 側邊欄的改進,讓您更容易存取您正在尋找的工具。升級到最新版本的 VS Code 和 Flutter 和 Dart 擴展,以存取改進的側邊欄。

Flutter 側邊欄是自適應的,可以調整大小以適合您的工作區

此版本還包含對 DevTools Extensions 框架的一些重大改進。您現在可以在除錯 Dart 或 Flutter 測試時使用 DevTools 擴展(由您的套件相依之一提供的工具),或者甚至在您沒有除錯任何內容時,但只是在 IDE 中撰寫程式碼時使用。因此,如果您想在這些使用者旅程中使用工具(或建立工具!),現在已經可以了。

若要進一步了解 Flutter 3.24 中包含的所有更新,請查看 DevTools 的發行備註 2.35.02.36.02.37.2

重大變更和棄用

此版本中的重大變更包括對 Navigator 的頁面 APIPopScope 中的泛型Flutter 網頁的預設渲染器 的變更,以及一些新的棄用。在 重大變更頁面 上查看完整的遷移指南。

與往常一樣,非常感謝社群為 貢獻測試 - 這些測試幫助我們識別出這些重大變更。若要進一步了解,請查看 Flutter 的重大變更政策

結語

Flutter 成功背後的核心是您 - 我們非凡的社群。沒有您无數的貢獻和堅定的熱情,這個版本是不可能實現的。我們衷心感谢您。

若要深入了解此版本中所取得的成果,我們邀請您查看 發行備註變更日誌,以獲取 Flutter 3.24 中加入的內容的完整列表。

Flutter 3.24 與 Dart 3.5 現在已在 stable channel 上提供。開始使用 Flutter 的最新旅程就像運行 flutter upgrade 一樣簡單。我們迫不及待想看看您會建立什麼!


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

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

使用 Flutter、Firebase Genkit 和 Gemini API 為經典文字遊戲添加趣味和實用性

今年的 I/O,Very Good Ventures 與 Google 的 Flutter 和 Firebase 團隊合作,創造了一種獨特的數位體驗,以展示 Gemini API 的強大功能。

填字遊戲的趣味(和挑戰)在於解決線索以完成棋盤。我們今年在 I/O 上討論過的所有內容,自然成為字詞和線索的起點。為了生成遊戲內容,我們向 Gemini Advanced 提供了主題演講的影片,並要求它建立一個與科技相關的熱門字詞和線索列表,使玩遊戲成為了解今年 I/O 公布的所有內容的有趣方式。

請繼續閱讀,了解我們如何使用 Flutter 建立 UI,並查看遊戲的開源程式碼,您可以在 GitHub 上存取。

如何玩

當您登入拼圖時,會提示您選擇您的隊伍。當您正確回答一個線索時,單詞將填入,並且格子的顏色會變為您的隊伍顏色。您的隊伍將為您解決的每個單詞獲得積分,如果您連續解決單詞而不請求提示,則您將獲得額外積分。

需要提示嗎?點擊 提示 按鈕,然後提出不超過十個關於隱藏單詞的是非題。Gemini API 會私下回答您的問題,以便您可以填寫更多單詞,並幫助您的隊伍取得勝利!

提示 功能的設計是一個很好的例子,說明不同的技術如何協同工作來解決問題。提示由 Firebase Genkit 提供支援,Genkit 是一個在 I/O 上宣布的用於 AI 開發的新框架,並且被部署為 Firebase 函式。

對 API 的網路請求包括線索的答案,因此為了將回應隱藏在訊息資料中,我們使用 Dart Frog 套件 建立了一個簡單的 Dart 後端,以使體驗更加健壯。Frog 後端呼叫 Genkit 以獲得提示,並從資料庫中擷取答案。這樣,玩家就不能簡單地檢查網路呼叫來找出遊戲的答案。

您可以在 Firebase 深入探討部落格 中閱讀更多關於 Genkit 流程的建構方式。

使用 Flutter 渲染高效能的填字遊戲棋盤

棋盤是遊戲的核心部分之一。我們優化了玩家在拼圖上的移動,以確保良好的效能,並為玩家提供最佳的使用者體驗。

我們考慮了兩種建立棋盤的選項:直接使用 Flutter 或使用 Flame 遊戲引擎。Flame 對此遊戲最引人注目的功能是其攝影機 API,它允許吉祥物輕鬆移動並支援縮放控制。但是,由於這幾乎是我們將使用的 Flame 的唯一功能,因此我們最終決定,對此場景而言,使用像 Flame 這樣的完整遊戲引擎有點過度。

尋找替代解決方案,我們探索了 InteractiveViewer Widget,它允許在自訂大小的畫布中渲染單詞,並使用矩陣轉換自由地移動吉祥物。InteractiveViewer 對我們的需求而言是一個更簡單的解決方案,具有較少的相依性和負載,這讓我們能夠更好地展示 Flutter 的靈活性與效能。

InteractiveViewer 的功能和靈活性

InteractiveViewer 內建了縮放手勢,但我們想要為桌面體驗添加更多直觀的按鈕。利用矩陣轉換,我們透過首先計算縮放比例的變化,並使用中心作為常數參考點來更新新的視窗,從而實作了縮放控制:

獲得新的暫時視窗後,我們必須確保它適合棋盤的邊界。我們必須允許兩種情況:當視窗比棋盤大時,或者當視窗的位置超出邊界時。我們透過調整縮放級別或視窗的位置來更新縮放比例變化的程度和視窗的轉換,以確保它適合邊界,如下面的程式碼所示:

最後,計算轉換並將其應用到 InteractiveViewer 控制項:

透過這段程式碼,我們擴展了 InteractiveViewer 的縮放控制,並根據我們的需求轉換了視窗。

使用 Flutter 中的 WebAssembly 提升效能

Flutter Web 應用程式的 WebAssembly 支援是今年 I/O 對 Flutter 社群的重要宣布之一。隨著全球玩家同時玩遊戲,效能是一個關鍵因素。我們利用了 WebAssembly (Wasm),它建構在 Flutter 中,以減少效能瓶頸並維持流暢的畫面更新率,特別是在遊戲中的角色和棋盤動畫方面。

Dart 後端和 Cloud Run:後端和前端之間的無縫程式碼共享

為了確保所有使用者都能享受流暢的遊戲體驗,我們的 Dart 後端使用 Dart Frog 套件 建構,並託管在 Google Cloud Run 上,以利用自動調整功能。這有助於維持最佳效能,無論活躍玩家數如何,因為遊戲會進行多次呼叫,例如每次建立使用者時,或者當玩家提交單詞或請求提示時。

使用後端來確認每個線索的答案,還可以讓我們保護填字遊戲,防止作弊。具體而言,應用程式使用 Flutter Firestore SDK 讀取資訊,但資料庫 允許 Dart 後端進行更改。這還有助於加快開發速度,因為我們可以在前端和後端使用相同的語言(Dart)。

例如,我們可以在 Player 資料模型中看到這種模式,它使用 Dart Frog API 建立一個玩家。

應用程式直接存取玩家排行榜,重複使用相同的模型,避免重複和不同步:

開始玩:解開 I/O 填字遊戲!

在您自己的所有橫向和縱向的輝煌中開始玩 填字遊戲。對於那些想要深入了解細節的人,請查看它的 開源程式碼開發者學習路徑,以展示我們如何建立它。觀看 Google I/O 回顧,以了解有關今年宣布的所有內容的更多資訊!


我們是如何建構它的:使用 AI 製作 I/O 填字遊戲 最初發佈在 Medium 上的 Flutter,人們在那裡透過突出顯示和回應這個故事來繼續討論。

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

回顧 Google I/O 2024 中的所有重大產品更新、新資源和成功案例

很難相信 Google I/O 2024 已經過去兩週了。我們對 Flutter 社群的支持表示衷心的感謝 - 這種能量令人振奮!

Flutter logo illustration

我們在幾個部落格、影片和活動中分享了許多產品更新、資源、開發人員故事、技術會議和工作坊 - 我們知道要跟蹤所有這些內容可能很困難。

在下面,您將找到我們在 Google I/O 2024 中分享的所有內容的概述,以及關於您可以在夏季的柏林、班加羅爾、北京的 I/O Connect 和 I/O Extended 活動中與我們和其他 Flutter 社群成員聯繫的活動地點和日期的更新。

部落格文章

我們在 Dart 和 Medium 部落格中發布了 四篇新的部落格文章

我們還與 Android 團隊合作撰寫了一篇部落格文章,提供有關 如何為您的專案選擇正確的框架 的一些指南:Flutter、Jetpack Compose 和 Kotlin 多平台:

Google I/O 演講、Codelabs 和工作坊

主要的 Google I/O 活動特色是關於 Dart 和 Flutter 的一系列精彩演講。我們建議從 Flutter 的新功能 主旨演講 開始,然後繼續我們的 五個技術會議,這些會議涵蓋了 CameraX、自適應 UI、AI 代理、Gemini 和應用程式深層連結等主題。

我們還有 三個新的 Codelabs,全部集中在使用 Flutter 建立 休閒遊戲 上。它們可以幫助您開始使用 2D 物理以及添加聲音和音樂。若要了解更多詳細資訊,請查看新的 2D 物理遊戲工作坊

新的 Flutter 展示故事

Flutter 展示 展示了一系列 Flutter 應用程式,這些應用程式展示了您可以使用 Flutter 在行動、網頁和桌面端創建引人入勝的使用者體驗。我們為 Google I/O 2024 添加了 四個新的展示故事

  • 環球影城環球影城使用 Flutter 打造下一代體驗
  • SupercellFlutter 幫助 Supercell 將 Supercell ID 核心程式碼大小縮減 45%
  • EtermaxEtermax 透過 Flutter 提高開發人員效率
  • 維珍理財維珍理財透過 Flutter 整合應用程式開發

I/O Connect 活動

Google I/O 並未結束於美國加州山景城的 主要活動。在全球各地有許多 Google I/O 社群活動,以及在三個地點規劃的 Google I/O Connect 活動:

  • 2024 年 6 月 27 日,德國柏林的 I/O Connect
  • 2024 年 7 月 17 日,印度班加羅爾的 I/O Connect
  • 2024 年 8 月 7-8 日,中國北京的 I/O Connect

Dart 和 Flutter 團隊將參加所有三個 I/O Connect 活動,我們希望與你們中的許多人聯繫!如果您想參加活動,請務必 註冊。我們期待與您聯繫!


來自繁忙的 Google I/O 2024 的所有 Flutter 新聞 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

undefined

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

宣布全球遊戲挑戰賽的獲獎者

我們邀請 Flutter 和 Global Citizen 社群共同打造以幫助地球為目標的史詩級 Flutter 遊戲。來自超過 50 個國家的數千名熱情開發人員提交了數百個創新的遊戲專案。

每個專案都旨在賦予玩家知識和行動,以保護我們的星球。從資源節約到抗擊污染,這些遊戲提升了我們對迫切環境問題的整體意識,同時也真正好玩!我們深受參賽作品中令人難以置信的想法和熱情的啟發。

為我們的十強作品最後一次隆重揭曉

在 103 天的時間裡,這些專案團隊不斷地構思、開發、尋求意見和改進他們的專案。結果——誕生了令人興奮的遊戲,鼓勵我們都更深入地思考我們如何可以更可持續地生活。以下是它們,按字母順序排列!

Better World

各種環境主題,豐富多彩的視覺效果和音樂,以及與組織合作促進積極行動的想法。

Craftown

將經典的即時策略和資源管理遊戲玩法獨特地融合在一起,重點關注可持續性主題。

EcoShift Chronicles

以迷人的視覺效果和聲音設計鼓勵積極行動,讓玩家面對相關的選擇及其環境後果。

Gomiland

視覺上引人入勝、教育性、垃圾管理遊戲,靈感來自日本文化。

Last Bottle

迷人的設計和可收藏的元素,有效地傳達了它關於回收限制和批判性思考環境問題的核心訊息。

MGame - A waste management game

雄心勃勃的模擬遊戲,以引人入勝的方式呈現複雜的垃圾管理系統,讓人想起經典的城市建造遊戲。

Ocean Rangers

引人入勝的敘事、迷人的角色和策略性遊戲玩法元素,以獨特的視角呈現環境主題的熟悉類型。

PlasticPunk

城市建造風格的遊戲,以引人入勝的遊戲玩法和迷人的視覺效果,呈現出複雜的環境挑戰。

Waste Wise

垃圾分類遊戲,具有直觀的遊戲玩法,並有效地向玩家傳授正確的垃圾處理知識。

Whaley’s Bins Waste Sorting

垃圾分類遊戲,以創造性的方式進行回收教育,採用獨特的像素藝術視覺效果。

我們期待在紐約市與這些團隊共度一天,在 Google 辦公室舉辦研討會等等,並與 6 萬名 Global Citizen 在 2024 年 Global Citizen Festival 上慶祝!

但這些只是 30 多個在 Global Gamers Challenge 中獲得獎項的團隊中的 10 個,包括 Top 20 中的其他成員,您將在榮譽提名列表中看到它們。前往 flutter.dev/global-gamers/#winners 查看所有團隊!

恭喜所有獲獎者!

這還沒有結束

作者:Lisa Pak,Playing 4 the Planet Alliance 運營主管

全球遊戲挑戰賽可能即將結束,但可持續遊戲運動不會就此結束。在此挑戰賽期間開發的遊戲以及類似的挑戰(如 Global Game Jam)有可能接觸到數百萬玩家,在全球範圍內產生積極的環境變革漣漪效應。

若要與這個蓬勃發展的運動保持聯繫:

  • 加入社群:考慮加入專注於環保遊戲設計的線上社群和論壇。這些空間為分享您的作品並與其他開發人員交換想法提供了寶貴的機會。
  • 繼續玩可持續遊戲:關注 熱門遊戲,其中包含以時間限制的事件、挑戰和新關卡形式呈現的綠色啟用,讓玩家參與這個重要議題。我們的目標是接觸到盡可能多的人群,而這些遊戲可能是很好的靈感來源。
  • 讓您的聲音被聽到:撰寫您在可持續遊戲開發方面的經驗,指導有抱負的開發人員,或自行組織倡議。在分享您的知識和專業知識(無論是技術還是環境)時,您不僅支持社群的成長,而且也鼓勵其他人創造對地球產生積極影響的遊戲。

繼續打造

作者:Clayton Whittle,氣候 SIG 聯席主席

遊戲中的可持續性包括促進運動本身,將氣候和可持續性問題優先考慮到您團隊的遊戲設計實務中,並作為可持續遊戲產業的代言人堅持下去。

綠色遊戲設計是一個不斷發展的領域,在創造出產生切實可衡量影響的遊戲方面,不斷發展出更精密的實務。雖然沒有通用的綠色遊戲設計規則,但遵守標準指南可以顯著有利於任何遊戲設計團隊。

  • 了解您的受眾:有效的可持續遊戲始於了解您的受眾的需求和能力。由於可持續遊戲旨在以某種方式轉變玩家,因此了解受眾對於指導這種轉變至關重要。如果不了解受眾最初的立場,就難以引導他們到達期望的終點。
  • 具体化:集中您的訊息以提高其有效性。試圖用一款遊戲改變玩家的整個世界觀是不切實際的。相反,找出有意義的改變領域。
  • 推廣有效的行動:為玩家提供可操作的知識。向他們傳授可以採取的具有影響力的行動,以做出改變。如果玩家看到他們的行動如何在大規模上影響生態系統或社會,他們更有可能參與其中。
  • 小心 漂綠:避免表面上的可持續性努力。漂綠是指那些沒有真正整合可持續性問題的表面上的可持續性元素。雖然添加綠色藝術作品或將角色命名為「回收隊長」似乎很有吸引力,但如果遊戲玩法或敘事缺乏有意義的可持續性行動,玩家就能看穿這些表面上的聯繫。

請記住,開發具有影響力的綠色遊戲有无数种方式。您的想法和設計可能會超出這些指導方針,進入未知領域。適合您團隊的方法取決於您的使命和受眾。但是,將這些原則納入您的設計討論中有助於確保您的團隊始終专注于其影響使命。

Flutter 如何幫助您

以下是一些 Flutter 可以幫助您減少對遊戲運行位置的擔憂,並將更多時間花在為您的使命和受眾設計具有影響力的体验的方式。

  • Flutter 效率高: Flutter 的單一程式碼庫開發意味著您只需要撰寫您的遊戲一次,就可以部署到所有平台。像「狀態熱重載」等功能可以幫助您快速迭代,加速您的開發流程。
  • Flutter 容易學習:即使您不是專業的遊戲開發人員,從 Flutter 入门也比使用傳統的遊戲開發工具更容易。我們還提供了一些資源,例如 Flutter 休閒遊戲工具組 中的遊戲模板,可以為您提供一個起點,幫助您提升您的遊戲開發技能。

感謝所有參與了我們旅程的人!我們迫不及待地想看看您接下來會打造什麼!


宣布全球遊戲挑戰賽的獲獎者 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

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

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

宣布 Dart 3.4

Dart 3.4 今天正式發布!此版本展示了 Dart 和 Flutter 在 Flutter 3.22 / Dart 3.4 / IO24 文章中的共同努力,因此請務必在那裏獲得完整的資訊。這篇文章介紹了我們對 WebAssembly 的支援,並詳細說明了今年 Dart 語言的幾個主要路線圖項目之一:_宏_。

WebAssembly 更新

今天,我們很興奮地宣布,在最新的 Flutter 3.22 穩定版本中,Flutter Web 應用 已經完全支援 WebAssembly (Wasm)!

這項投資橫跨 Dart 和 Flutter 多年。如果您一直在關注這些發展,您會看到我們的漸進式改進:

  • WasmGC 提案標準化,
  • 加入了一個全新的 Dart 編譯器後端,用於生成 WasmGC 程式碼,以及
  • 重新設計 我們的 Web 和 JavaScript 互操作產品,以最佳支援 Wasm。

我們將繼續投資 WebAssembly。我們的下一個努力將在純粹的 Dart 應用程式中啟用對 Wasm 的完全支援,並完成一些缺失的功能(例如延遲載入)。Dart 中 Wasm 編譯的端到端工具仍在開發中,但您可以 嘗試預覽 在 stable 版本中使用一些臨時步驟。之後,我們還希望在 JS 環境之外 的 Dart 中支援 Wasm,例如標準 Wasm 執行時間,例如 wasmtime 和 wasmer。

Dart 宏:提升開發抽象層級

我們投入了多年時間設計 Dart 宏系統。為了改善 Dart 的開發體驗,宏提供了元程式設計解決方案,例如程式碼生成。此解決方案內建到 Dart 語言中,為開發人員提供最大的效能、效率和生產力。現在,我們準備提供此體驗的預覽!

Dart 開發人員長期以來的一個痛點是,JSON 資料的序列化和反序列化既瑣碎又乏味。在 Dart 中,製作一個可重複使用且功能強大的解決方案是一個挑戰,因為它出於效能原因不支持運行時反射。作為替代方案,我們依賴於程式碼生成解決方案,例如 JsonSerializable。這些依賴於在程式碼本身之前運行的外部工具,使開發人員的體驗變得複雜。

今天,我們宣布了一種用於 JSON 序列化和反序列化的全新方法的預覽:JsonCodable 宏。

宏是一種透過在編譯時內省其他程式碼來生成更多程式碼的程式碼類型。例如,以下是一個帶有新的 JsonCodable 宏的 Dart 類別 Vehicle:

1
2
3
4
5
6
7
8
9
10
11
@JsonCodable()
class Vehicle {
final String description;
final int wheels;
Vehicle(this.description, this.wheels);
}

void main() {
final jsonString = Vehicle('bicycle', 2).toJson();
print('Vehicle serialized: $jsonString');
}

那麼,它是如何運作的呢?toJson() 方法(以及配套的 fromJson() 建構函數)從哪裡來呢?這是一個用於簡化開發人員體驗的新宏系統的實驗性實作。當 Dart 編譯器看到 @JsonCodable() 註解時,它會立即實時找到 JsonCodable 宏的定義,並開始執行它。這會導致宏:

  1. 建立一個新的「增強類別 」;一種新的語言結構,允許為現有類別新增新的宣告。
  2. 讀取開發人員對 Vehicle 類別的定義,以確定它具有兩個欄位,descriptionwheels
  3. 在增強類別中新增一個新的 toJson 方法簽章。
  4. 填寫 toJson 方法的主體,以處理 descriptionwheels 欄位的序列化。

所有這些都在沒有延遲的情況下完成。整合的體驗支援我們現有的開發人員工作流程,例如熱重載,正如此螢幕錄影所示:

Screencast showing the experience of using a macro: Initially no toJson code completion exists, but after adding @JsonCodable to the class, the toJson code completion shows up immediately.

長期宏目標

最終目標是讓社群能夠建立自己的宏。這提高了 Dart 程式設計的抽象層級。以資料類別為例,這是 投票數最高 的 Dart 語言功能。我們考慮過在 Dart 中新增對資料類別的內建支援,但了解到人們對此類結構應該支援哪些內容意見分歧很大,以至於我們無法自己設定標準。欄位是否應該不可變?它是否應該支援相等?那 hashCode 呢?也許還有 toString ?我們得出結論,支援宏系統會是更好的方法。社群可以建立自己的抽象類型,允許更多可擴展的實驗和多樣性。

設計和實作如此強大的宏系統是一項艱鉅的任務。我們決心以一種不會對核心 Dart 開發人員用例(例如程式碼輔助和完成、程式碼分析和熱重載)產生不利效能影響的方式來進行。考慮到這一點,我們採取了分階段的方法:

  • 在今天的版本中,我們提供了一個單一宏 JsonCodable 的預覽,以便使用者可以開始熟悉使用宏的開發體驗。
  • 如果這個宏的推出順利,我們希望在後續版本中將 JSON 宏升級到穩定版本。
  • 與此同時,我們正在努力完成底層宏系統的設計和實作。一旦我們對其效能和穩定性有信心,最終的目標將是讓 Dart 開發人員社群能夠定義自己的宏。

完成這些階段還有很多工作要做。同時,您可以閱讀文件以了解更多關於 Dart 宏系統 的資訊,並立即嘗試 JsonCodable 宏 的預覽。

其他改進

與往常一樣,此版本包含所有用於提供最佳 Dart 版本的持續開發。在此版本中,我們做出了以下改進:

  • 解決了超過 50% 的分析器程式碼完成錯誤。(請繼續提交 議題!)
  • 改進了條件運算式、if-null 運算式和 switch 運運算式的類型分析與語言規範的對齊(變更日誌)。
  • dart:cli 函式庫中移除不完整且不一致的工具,以償還 Dart VM 中的技术债务。
  • 解决了几个不足之处,以改进新的 dart:js_interop 函式庫。

查看 變更日誌 以獲取完整的故事!不要忘記閱讀此版本中關於我們共同努力的 Dart 和 Flutter 聯合部落格文章 以獲取完整的故事!


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

undefined

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

宣布 Flutter 3.22:WebAssembly、圖形渲染增強功能和更多 AI 整合選項

歡迎回來,一起迎接另一個令人興奮的 Flutter 穩定版本!這次,我們很高興推出 Flutter 3.22。我們將 WebAssembly 帶到穩定通道,為 Android 上的 Impeller 提供功能齊全的 Vulkan 後端,有望帶來更流暢的圖形和大幅提升效能。我們還推出了精簡的工作流程,其中包含新的 Widget 狀態屬性、動態視圖大小調整和改進的表單驗證功能。但這還不是全部——您將發現風味條件的資產捆綁、Firebase 上 Vertex AI 的預覽版本(使用 Dart),以及更新的 DevTools,讓您的生活更輕鬆。

自上次更新以來,僅僅幾個月,我們就從 Flutter 社群合併了令人印象深刻的 1595 個拉取請求,其中有 37 位新社群成員首次為 Flutter 貢獻!

因此,深入了解 Flutter 社群帶給這個最新版本的最新功能和增強功能吧!

WebAssembly

隨著 Flutter 3.22 的發佈,Wasm 現在可以在穩定通道上使用,提供顯著的效能提升。在我們在 M1 MacBook 上使用 Chrome 進行的內部基準測試中,Wonderous 應用程式的畫面渲染時間平均提高了 2 倍,在最壞的情況下提高了 3 倍。

這些增強功能對於具有動畫和豐富轉場的應用程式至關重要,在這些應用程式中,保持流暢的畫面速率至關重要。Wasm 透過減少效能瓶頸來幫助實現這一點,從而帶來更流暢的動畫和轉場。若要開始在您的 Flutter 網頁應用程式中使用 Wasm,請查看我們的 Dart Wasm 文件Flutter Wasm 文件。如需完整的公告,請訪問 Google I/O 部落格文章中的 Flutter

引擎

Flutter 3.22 為 Impeller 引入了重大更新,Impeller 是驅動 Flutter 應用程式的渲染引擎。主要亮點包括完成 Android 上的 Vulkan 後端,以實現更流暢的圖形和改進的效能,為模糊效果和複雜路徑渲染進行持續優化,以及一個新的實驗性 API,用於使用 Impeller 進行測試。根據我們的路線圖,我們致力於提升 Impeller 的品質和效能,包括完成 iOS 到 Impeller 的遷移和擴展 Android 支援。

Impeller

Android 上的 Vulkan 後端功能完整

在此版本中,Impeller 的 Android Vulkan 後端已具備完整的功能。特別是在過去的幾個月裡,團隊一直在努力完成 快速進階混合 的實作,支援使用 FragmentProgram API 的自訂片段著色器,PlatformView 支援(儘管它需要 少量 API 遷移),以及完全實作 所有模糊樣式

Android 預覽

在 3.19 穩定版本中,在發佈 Impeller 的 OpenGL 後端的改進之後,我們邀請使用者在支援和不支援 Vulkan 的 Android 設備上試用 Impeller。在過去的幾個月裡,在評估 OpenGL 後端的效能並估計 Vulkan 後端的剩餘工作量之後,我們決定將精力集中在首先讓 Vulkan 後端做好生產準備。

Impeller 解決了著色器編譯卡頓的問題。此外,在我們的基準測試中,它在平均值、第 90 個百分位數和第 99 個百分位數的畫面時間方面優於傳統渲染器。因此,我們認為 Vulkan 後端在 Android 上的效能是可以接受的。在此版本(3.22)中,選擇加入 Impeller 的應用程式將在有 Vulkan 支援的地方使用 Vulkan 後端。在將來的版本中,這將成為預設值。當選擇加入 Impeller 的應用程式在不支援 Vulkan 的設備上運行時,Flutter 將會自動無縫切換為使用 OpenGL ES 和 Skia。您無需採取任何措施。在未來,當我們認為 OpenGL ES Impeller 後端已做好生產準備時,這種回退也會使用 Impeller。

隨著 Android 上的 Impeller 預覽繼續在 3.22 穩定版本週期中進行,我們請求 Flutter 開發人員升級到最新的穩定版本,並在 啟用 Impeller 時提交有關任何發現的不足的錯誤。在此階段的回饋對確保 Impeller 在 Android 上取得成功以及我們能夠在今年晚些時候的版本中自信地將其設為預設渲染器至關重要。Android 硬體生態系統非常多元。因此,關於 Impeller 最有用的回饋應包括有關發生問題的特定設備和 Android 版本的詳細資訊。

模糊效能改進

模糊已在 iOS 和 Android 上的 Impeller 中 重新實作。特別是,這種新方法類似於 Skia 的方法,在 基準測試 中將模糊的 CPU 和 GPU 時間減少了近一半。

下圖顯示了在 iPhone 11 設備上進行的病態基準測試中的最壞情況、第 99 個百分位數、第 90 個百分位數和平均畫面柵格化時間以及 GPU 畫面時間(以毫秒為單位),旨在突出顯示模糊效能。在重寫 Impeller 的模糊之後,背景濾鏡模糊的 CPU 和 GPU 成本都幾乎減少了一半。這種改進的規模也適用於非病態情況,正如典型應用程式中所出現的那樣。

在 iPhone 11 設備上進行的病態基準測試中的第 99 個百分位數、第 90 個百分位數和平均畫面柵格化時間以及 GPU 畫面時間(以毫秒為單位),旨在突出顯示模糊效能

Stencil-then-Cover

iOS 和 Android 上的 Impeller 都已 轉移到新的渲染策略,該策略基於 OpenGL Redbook 中“使用模板緩衝區繪製填充的凹多邊形”章節中描述的 Stencil-then-Cover 方法。團隊成員在 GitHub 問題 #123671 中討論了這種技術在 Flutter 中的應用。

這種方法解決了柵格執行緒在 CPU 上為複雜路徑(例如,SVG 和 Lottie 動畫)計算細分時花費過多時間的問題。更改之後,包含複雜路徑的畫面的總畫面時間(CPU 上的 UI 執行緒 + CPU 上的柵格執行緒 + GPU 工作)要低得多。使用者會注意到 Lottie 動畫和其他複雜路徑渲染得更加流暢,CPU 利用率更低,而 GPU 利用率略微更高。

(左) Lottie 動畫。以前,Impeller 在最近的 iPhone 上需要 64ms/畫面 的柵格執行緒 CPU 時間才能渲染它。(右) 在我們實施 Stencil-then-Cover 優化之後,在相同設備上渲染的相同動畫。柵格時間幾乎快了 10 倍。

雖然對這些改進感到滿意,但我們還有更多工作要做。除了其他機會之外,我們意識到折線生成在 CPU 配置檔案中仍然很突出,我們打算調查將此工作也轉移到 GPU 上。

新的 API

雖然仍處於實驗階段,但 flutter test 現在接受 --enable-impeller 標誌,它使用 Vulkan 後端來執行 Impeller。

架構

Widget 狀態屬性

MaterialState 已被移動到 Material 函式庫之外,並被重新命名為 WidgetState,以便於 Cupertino、基本 Flutter 框架和套件作者使用。如需有關遷移到新的 WidgetState 的更多資訊,請查看 遷移指南

動態視圖大小調整

對動態視圖大小調整的 增強功能 有利於構建響應式佈局的開發人員,確保在各種設備螢幕上具有更好的 UI 自適應性。

改進的表單驗證

感謝 Flutter 社群成員 SharbelOkzan貢獻,Flutter 3.22 帶來了更靈活的表單驗證方法,使開發人員能夠建立更健壯的使用者輸入處理,從而提升可用性和安全性。

2D API 中的協變

減少在 2D 圖形 API 中進行類型轉換的需要,簡化了開發工作流程並提高了效能,這對於遊戲和複雜動畫非常重要。

風味條件的資產捆綁

使用 風味 功能的開發人員現在可以將個別資產配置為僅在為特定風味構建時進行捆綁。如需更多資訊,請查看 根據風味有條件地捆綁資產

使用 Dart 套件變換資產

使用者現在可以將 Dart 套件配置為在捆綁時變換應用程式的資產。如需更多資訊,請查看 在構建時變換資產

Android

深度連結

深度連結可以顯著提高 Flutter 應用程式中的使用者體驗,充當將使用者無縫引導到應用程式中特定內容的捷徑,從而提升參與度和推動銷售。雖然 iOS 的通用連結和 Android 的應用程式連結因其安全性及其使用者友好的特性而受到高度推薦,但設定它們可能有點棘手。

在上次 Flutter 穩定版本中,我們在 DevTools 中引入了一個深度連結驗證工具,該工具支援為 Android 應用程式檢查網頁配置。在此版本中,我們添加了一組新的功能來幫助驗證 Android 清單檔案中的設定。

如需有關使用此工具的更多資訊,請查看 驗證深度連結

預測返回手勢

Flutter 現在為 Android 的即將推出的預測返回功能提供了更多支援,使用者可以在返回手勢期間預覽上一個路由,甚至預覽上一個應用程式。這仍然是 Android 設備上的功能標誌,但您可以在 GitHub 上找到有關如何自行嘗試它的詳細資訊。

Flutter 工具強制執行 Gradle、AGP、Java 和 Kotlin 上的版本要求

在此版本中,Flutter 工具強制執行有關它支援的 Gradle、Android Gradle Plugin (AGP)、Java 和 Kotlin 版本的策略。最初,該工具只提供警告。

目前,支援的版本範圍如下:

  • Gradle - 完全支援 7.0.2 到最新版本,否則警告
  • AGP - 完全支援 7.0.0 到最新版本,否則警告
  • Java - 完全支援 Java 11 到最新版本,否則警告
  • Kotlin - 完全支援 1.5.0 到最新版本,否則警告

在下次主要版本更新中,這些警告將變為錯誤,可以使用 --android-skip-build-dependency-validation 標誌覆蓋。更一般而言,該工具會在完全放棄對這些相依項目的給定版本的支援(生成錯誤)之前,至少提供一個版本的警告。

這項策略在 相關的設計規範 中有討論。歡迎隨時發表意見和回饋。

支援在 Android 上的 Gradle 組建指令碼中使用 Gradle Kotlin DSL

Gradle Kotlin DSL 現在在 Flutter 中得到支援,為傳統的 Gradle Groovy DSL 提供了一個替代方案。這種支援允許提供更好的程式碼編輯體驗,其中包含自動完成、快速存取文件、原始碼導航以及上下文感知重構。

此初始支援由 GitHub 使用者 bartekpacia 貢獻。開發人員現在可以选择使用 Kotlin 重寫他們的 Gradle 組建指令碼,以利用這些優點,儘管 Flutter 工具目前還不允許在使用 flutter create 時選擇 Kotlin 而不是 Groovy。

如需更多詳細資訊,請查看 bartekpaciaPR 140744

平台視圖改進

給所有 Flutter 應用程式開發人員的提醒!如果您使用 Flutter 構建依賴原生 Android 組件(如地圖、網頁視圖或某些 UI 元素)的應用程式,我們有一些重要資訊。

由於 Android 14 中的一個錯誤,使用舊版 Flutter 構建的應用程式可能無法在運行此新 Android 版本的設備上正常工作。

Flutter 3.22 修複了這個問題,並改進了 Android 應用程式中這些原生組件的整體效能。因此,為了確保您的應用程式在所有 Android 設備上順暢運行,請確保使用 Flutter 3.22 重新構建和發佈您的應用程式。

此更新還包括幕後改進,以使 Android 上的平台視圖更加可靠和高效。

KitKat 支援結束

Flutter 的最低支援 Android 版本現在是 Lollipop (API 21)。從 Flutter 的 3.22 穩定版本開始,Flutter 將不再在運行 Android KitKat (API 19) 的設備上工作。如需更多詳細資訊,請查看我們的 棄用指南

iOS

平台視圖效能

我們理解 iOS 上的平台視圖效能一直是許多 Flutter 開發人員的痛點。這在使用平台視圖時,特別是在捲軸視圖中很明顯。

最近的更新直接解決了這些問題,在嵌入文章中的多個內聯廣告等場景中取得了顯著的改進。以下是一些 基準測試 中的一些關鍵改進:

  • 降低 GPU 使用率: GPU 使用率降低了 50%,從而減少了功耗,並可能帶來更流暢的使用者體驗。
  • 改進畫面渲染: 平均畫面渲染時間減少了 1.66ms(33%)。
  • 最小化卡頓: 最壞情況下的畫面渲染時間減少了 3.8ms(21%)。

如果您以前在捲軸視圖中使用多個平台視圖(如廣告、地圖等)時遇到效能挑戰,這些優化可能有助於提供更流暢、響應更靈敏的捲軸體驗。請試用一下,並告訴我們您的想法。

生態系統

Vertex AI for Firebase Dart SDK 預覽版本發佈

Vertex AI for Firebase 產品已發佈到公開預覽版,其中包含 Dart SDK。這使您可以使用 Gemini API 為您的 Dart 或 Flutter 應用程式構建生成式 AI 功能,並考慮到生產、效能和企業規模。該 SDK 集成了 Firebase 應用程式檢查,這可以保護您的 API 調用,並保護您的後端基礎設施免受嚴重的威脅,例如計費欺詐、釣魚和應用程式偽裝。跳入 Dart 入門,並使用促銷代碼免費開始使用。

Google AI Dart SDK 仍然可用,建議僅用於原型設計。Google AI 具有免費使用權限(在限制範圍內,以及在有提供的地方),並提供按使用付費定價。如果您一直在使用 Google AI Dart SDK 進行原型設計,並且已準備好遷移到 Firebase 上的 Vertex AI,請查看 遷移指南

DevTools 更新

我們繼續改進 DevTools,這是 Dart 和 Flutter 的效能和除錯工具套件。此版本包含效能改進、通用潤色以及新的功能,例如在時間軸中包含 CPU 樣本、進階過濾以及支援匯入和匯出記憶體快照。

其他值得注意的改進與 devtools_extensions 和 devtools_app_shared 套件一起發佈,這些套件支援 DevTools 擴展作者。我們添加了對將擴展連接到新的 Dart Tooling Daemon (DTD) 的支援,這使 DevTools 擴展可以存取由其他 DTD 客戶端(例如 IDE)註冊的公開方法,以及允許存取用於與開發專案進行互動的最小檔案系統 API。

若要進一步了解 Flutter 3.22 中包含的所有更新,請查看 DevTools 的發行備註 2.32.02.33.02.34.1

Flutter 的 Google 行動廣告 SDK

對於那些使用廣告為 Flutter 應用程式獲利的人來說,我們有一些好消息:Flutter 的 Google 行動廣告剛剛發佈了 5.0.1 版本的重大更新!

增強對使用者訊息平台 (UMP) SDK 的支援: 此更新添加了對 Android UMP SDK 版本 2.2.0 和 iOS UMP SDK 版本 2.4.0 中的最新 API 的支援。UMP SDK 對遵守隱私法規至關重要,讓您更容易獲得使用者對個人化廣告的同意。此新版本引入了幾個新的 API,以簡化同意收集過程。

擴展的中介合作夥伴: 我們透過提供與熱門廣告合作夥伴的整合,擴展了您的廣告變現範圍,這些合作夥伴包括 UnityMetaAppLovinIron SourceMintegralPangleDT ExchangeInMobi 以及 Liftoff。您現在可以使用擴展的中介選項和簡化的實作,最大限度地提高應用程式的收入。

我們鼓勵您在 Flutter 應用程式中試用這些新功能,並告訴我們您希望我們支援哪些其他中介合作夥伴。您的回饋對我們持續改進 Flutter 的 Google 行動廣告 SDK 至關重要。

重大變更和棄用

移除 v1 Android 嵌入

版本一 Android 嵌入的刪除正在進行中。這可能對大多數應用程式沒有影響,因為

  1. 版本二已成為預設版本多年。
  2. Flutter 工具會阻止構建版本一應用程式,除非使用 --ignore-deprecation 標誌特別覆蓋。

此版本完全中斷了 Flutter 工具對 v1 應用程式的支援。不再可以用此方法覆蓋。

插件作者,請注意: 當 v1 android 嵌入最初被棄用時,為插件作者撰寫了一個遷移文檔:https://docs.flutter.dev/release/breaking-changes/plugin-api-migration。作為此遷移的一部分,建議插件作者透過在其 Plugin.java 中包含具有以下簽章的方法,來保持對使用 v1 嵌入的應用程式的支援:

1
public static void registerWith(@NonNull io.flutter.plugin.common.PluginRegistry.Registrar registrar) 

我們計劃在下一個版本中完全刪除 v1 Android 嵌入,屆時包含具有此簽章的方法的插件將無法編譯(因為它會引用 v1 android 嵌入中的類型)。

它目前沒有任何作用,因為此版本中斷了使用 v1 嵌入的應用程式。我們建議插件作者儘快發佈已移除 v1 程式碼的插件更新版本,以避免在將來的 Flutter 版本中出現中斷。例如,請查看 PR 6494,該 PR 移除 Flutter 團隊維護的插件。

在 3.22 中移除的棄用

此版本中的 重大變更 包括在 v3.19 發佈後過期的棄用 API。若要查看所有受影響的 API,以及其他內容和遷移指南,請查看 此版本的棄用指南。這些 API 中的許多都由 Flutter fix 支援,包括 IDE 中的快速修復。可以使用 dart fix 命令列工具評估和應用批量修復。

與往常一樣,非常感謝社群為 貢獻測試 - 這些測試幫助我們識別出這些重大變更。若要進一步了解,請查看 Flutter 的重大變更政策

結語

Flutter 成功背後的核心是您 - 我們非凡的社群。沒有您無數的貢獻和堅定的熱情,這個版本是不可能實現的。我們衷心感謝您。

準備探索 Flutter 3.22 嗎?深入了解完整的發行備註和變更日誌,啟動您的終端機,然後運行 flutter upgrade。我們迫不及待想看看您會建立什麼!


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

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

在 Google I/O 2024 上推出 Flutter 3.22 和 Dart 3.4

過去幾個月,Dart 和 Flutter 的空中交通管制特別繁忙,但我們很高興宣布 Flutter 3.22 和 Dart 3.4 已於今天順利推出,並可供使用,恰逢今年的 Google I/O

我們始終致力於提供強大的語言和框架配對,讓您能夠從單個共用程式碼庫構建精美、豐富且快速的應用程式,以便您可以將應用程式交付給行動、網頁和桌面上的使用者,而無需分散您的產品路線圖。

Flutter 3.22 和 Dart 3.4 提供了效能改進和平台特定的細化,使我們更接近這個願景。我們特別興奮地分享我們在 Wasm 方面的旅程,但您還會發現更多內容,包括改進的 Impeller 渲染引擎、iOS 上更流暢的視覺效果和更低的 CPU 使用率、使用 Android 的預測性返回手勢增強的平台導航、使用 Google Mobile Ads SDK 擴展的變現選項,以及 DevTools 中一個全新的強大深度鏈接驗證器。Dart 開發人員將享受使用 IDE 中的 dart fix 簡化 API 遷移以及用於進階分析的新 DevTools 功能。此外,您現在可以預覽用於 Firebase Dart SDK 的 Vertex AI,將 AI 驅動的功能與強大的安全措施相結合。

今天,我們還將重點介紹頂尖公司如何使用 Flutter 來提高生產力並構建高效能的體驗。我們將重點介紹一些特別令人興奮的功能,這些功能讓我們更接近我們的目標,即在所有平台上提供類似原生的效能,並包括我們對生產力、開發人員體驗和遊戲的投資的最新更新。

如果您想詳細了解版本中包含的所有內容,請查看專門的 FlutterDart 文章。是時候放手一搏了!

Flutter 在行動中

Flutter 開發人員正在忙碌地將大型新應用程式發佈到應用程式商店。讓我們看看其中幾個。

幫助大型企業級應用程式在行動端和網頁端交付

  • 在英國,金融機構 維珍金融 在其行動銀行和信用卡應用程式套件中使用 Flutter,以統一應用程式開發流程,加快變更速度,並提供行業領先的使用者體驗。
  • 美國保險公司 GEICO 最近 分享了 Flutter 如何幫助他們改進 iOS、Android 和網頁上的品牌使用者體驗,減小程式碼庫的大小,並提高開發效率,所有這些都在規模上實現。
  • 環球影城目的地與體驗 發佈了他們好萊塢、大阪和奧蘭多公園的新 Flutter 行動應用程式。觀看下面的影片,了解他們為什麼選擇 Flutter 以及 Flutter 的表現如何。

超越行動端和網頁端

  • Canonical 團隊一直在與 Flutter 合作自 2021 年起 為 Ubuntu 提供 Flutter 生態系統 的支援。在過去的一年中,Canonical 團隊使用 Flutter 從頭開始重建了 Ubuntu 安裝程式。
  • LG 選擇 Flutter 來增強他們的智慧電視作業系統 webOS。Flutter 的效能、生產力和強大的生態系統讓 LG 可以快速開發和部署 webOS 系統應用程式,這些應用程式可以順暢運行。到 2025 年,Flutter 將為全球數千萬台 LG 電視提供系統應用程式。

這些成功案例鼓舞著我們,我們致力於讓 Flutter 變得更好。讓我們深入了解最新的產品更新,展示我們正在做些什麼來讓您能夠構建更加驚豔的應用程式、遊戲和體驗。

WebAssembly:在網頁上追逐原生效能

今天,我們宣布在我們的穩定版本中支援將 Flutter 網頁應用程式 編譯 為 WebAssembly (Wasm)。這是一種用於網頁瀏覽器的令人興奮的新指令格式,它提供了一種可移植的、平台中立的二進制程式碼格式。

我們對 Wasm 的支援是一項深入的、多年來的投資。首先,我們與 Chrome 團隊合作,在 WebAssembly 中為像 Dart 這樣的高級管理語言定義支援,這些語言通常使用垃圾回收。這導致了 WasmGC 提案,該提案現在已成為一個完整的標準,並在 Chrome(Chromium 119 及更高版本)和 Firefox(120 及更高版本)中提供了運行時實施,預計其他瀏覽器供應商將會效仿。接下來,我們添加了一個全新的 Dart 編譯器後端以生成 WasmGC 程式碼,而 Dart 和 Flutter 團隊合作執行編譯後的應用程式程式碼和 Flutter 渲染引擎作為 Wasm 模組,並提供有效的 Wasm 到 Wasm 的互操作性。

那麼最終結果是什麼?我們看到了效能的大幅提高,接近我們在運行機器程式碼的行動和桌面設備上的效能。在我們的內部基準測試中(在 M1 MacBook 上使用 Chrome),Wonderous 的畫面渲染時間在一般情況下提高了 2 倍,在 99% 的最差情況效能下提高了 3 倍。改進的渲染效能對於具有動畫和豐富轉場的需要大量資源的應用程式至關重要,在這些應用程式中,超出畫面預算(分配給渲染下一畫面的時間)會導致非常明顯的卡頓。Wasm 可能會消除這種卡頓,如下圖所示,Wonderous 應用程式使用傳統的 JS 編譯和 Wasm 編譯進行比較。

比較Wonderous 範例應用程式中 Javascript 和 Wasm 的渲染速度。

Flutter 網頁應用程式的 Wasm 編譯今天在穩定版本中可用。若要開始使用,請查看我們的 Dart Wasm 文檔Flutter Wasm 文檔

Dart macros:提高開發抽象級別

我們致力於提供一流的開發人員體驗。這意味著要解決 Dart 開發人員長期存在的痛點,例如序列化 JSON 資料。

這是一種普遍的模式,既簡單又乏味。目前的解決方案意味著要麼手動地完成編碼和解碼樣板,要麼在程式碼生成解決方案(例如 JsonSerializable 套件)的形式中添加額外的工具。

今天,我們宣布了一個用於 JSON 的更好選項的預覽版本:JsonCodable macro。

macros 是創建更多程式碼的程式碼。它們就像程式碼生成,只是 macro 系統 內建於 Dart 中 並在您編輯和運行程式碼時 實時發生。這是一種整合的體驗,沒有延遲,完全支援我們現有的開發工作流程,例如熱重載,如這個螢幕截圖所示:

螢幕截圖展示了使用 macro 的體驗:最初沒有 `toJson` 程式碼完成,但在為類別添加 `@JsonCodable` 之後,`toJson` 程式碼完成立即顯示。

我們很興奮地看到 macros 為我們的開發人員解決各種問題。例如,資料類別,是 票數最高的 Dart 語言功能。除了特定應用之外,我們的最終目標是在 Dart 中擁有一個 macro 系統,允許使用者創建自己的 macros 並提高 Dart 程式設計的抽象級別。

設計和實作這樣一個強大的 macro 系統是一項巨大的任務,因此目前沒有設定穩定版本的時間 - 有關更多詳細資訊,請查看 Dart 3.4 文章。同時,今天就嘗試一下 JsonCodable macro 的預覽版本。有關更多資訊,請查看 macros 文檔

Flutter 遊戲開發的新資源

我們在遊戲方面的早期投資取得了令人鼓舞的成果,包括來自行業領導者(如 EtermaxSupercell)的成功案例,他們都在利用 Flutter 的功能和靈活性來有效地提供愉悅的使用者體驗並擴展其覆蓋範圍。

今天,我們很興奮地使用這些 Flutter 遊戲開發人員的新資源來延續這種勢頭:

賦能可持續的遊戲開發

在 2024 年 1 月,在受到他們使用 Flutter 的 故事 的啟發下,我們與全球公民合作,挑戰我們的社群使用 Flutter 設計、構建和發佈可持續性遊戲。這些遊戲旨在激勵和賦能玩家,讓他們為環境採取一些微不足道但有意義的行動。今天,我們宣布 10 位獲獎者

恭喜所有獲獎者!

更多探索

今天我們只有時間重點介紹這些內容,但還有許多其他我們沒有涉及的令人興奮的改進。以下是一些需要注意的其他事項:

  • 您可以 預覽用於 Firebase Dart SDK 的 Vertex AI,在 Dart 或 Flutter 應用程式中使用 Gemini API 來實現 AI 驅動的功能。SDK 與 Firebase 應用程式檢查相結合,保護您的 API 調用,並保護您的後端基礎架構免受嚴重的威脅,例如計費欺詐、釣魚和應用程式偽造。有關詳細資訊,請查看我們的 AI 頁面
  • Impeller,我們的 下一代渲染引擎,現在在 Android 上功能齊全。
  • Android 的預測性返回手勢 現在支援在 Flutter 應用程式中導航時,以及導航到其他應用程式或主畫面時。
  • iOS 上的 平台視圖 已進行效能優化,將 CPU 使用率降低了高達 50%。
  • Google Mobile Ads SDK 已擴展以支援更多廣告合作夥伴和調解選項。
  • DevTools 有一個新的 深度鏈接驗證器,它可以幫助您識別和解決 Android 深度鏈接配置中的錯誤,以便您可以更輕鬆地將網頁體驗與 Flutter 應用程式連接起來。
  • dart fix,我們的 API 遷移工具,現在可以直接從 IDE 中調用。
  • DevTools 現在支援時間線上進階篩選和 CPU 樣本。

前往 Flutter 技術文章Dart 3.4 文章 獲取有關這些內容以及更多內容的更多詳細資訊。

與往常一樣,我們非常感謝您的持續支援、熱情、熱忱和回饋。沒有您,這個專案是不可能實現的,我們迫不及待地想看看您將如何繼續推動 Flutter 向前發展。

Flutter 完畢。我們希望很快再見到您!


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