Flutter 2 有什麼新功能?

已發表: 2022-03-10
快速總結 ↬ Flutter 已經從適用於 Android/iOS 的跨平台移動開發 SDK 轉變為允許您在 Windows、Linux 和 macOS 上的瀏覽器中本地運行相同代碼的工具。 在 Flutter 2 中,非移動端 Flutter 開發開始變得更加可行。

去年,我在 Smashing Magazine 上寫了兩篇關於在 Web 和桌面平台上使用 Flutter 的文章。 第一篇文章是對 Web 和桌面開發的一般介紹,重點是構建響應式 UI; 第二篇文章是關於您在嘗試開發可在多個平台上運行的 Flutter 應用程序時可能面臨的挑戰。

那時,Flutter 團隊認為 Flutter 對非移動平台的支持並不穩定且可用於生產,但現在情況發生了變化。

Flutter 2 來了

3 月 3 日,Google 舉辦了 Flutter Engage 活動,Flutter 2.0 發布。 這個版本確實是一個真正的 2.0 版本,許多變化有望使 Flutter真正為超越移動應用程序開發做好準備。

理解 Flutter 2.0 為何重要的核心變化是, Web 開發現在正式成為穩定通道的一部分,桌面支持也將很快出現在穩定通道上。 事實上,它目前以類似發布候選的形式啟用,作為穩定通道中的早期發布 beta 快照。

在公告中,谷歌不僅暗示了 Flutter 的未來會是什麼樣子。 還有一些實際例子表明,大公司已經在開發 Flutter 應用程序,用性能更好的應用程序替換他們現有的應用程序,讓開發人員更有效率。 例如,世界上最大的汽車製造商豐田現在將使用 Flutter 在他們的汽車上構建信息娛樂系統。

另一個有趣的公告——展示了 Flutter 作為跨平台 SDK 的改進速度有多快——是 Canonical 的公告,除了使用 Flutter 開發新的 Ubuntu 安裝程序外,他們還將使用Flutter 作為構建桌面應用程序的默認選項

他們還發布了 Ubuntu 的 Yaru 主題的 Flutter 版本,我們將在本文後面使用它來構建一個 Flutter 桌面應用程序,該應用程序在 Ubuntu 桌面上看起來很完美,同時還使用了更多新的 Flutter 功能。 您可以查看 Google 的 Flutter 2 公告以獲得更完整的圖片。

讓我們看一下 Flutter 2.0 版進入穩定通道的一些技術更改,並使用 Flutter構建一個非常簡單的示例桌面應用程序,然後我們就可以和不能使用 Flutter 的特定項目類型得出一些結論現在。

跳躍後更多! 繼續往下看↓

更大設備的一般可用性更改

根據公告,Flutter 已經進行了許多更改,以便為非移動設備提供更好的支持。

例如,Web 和桌面應用程序所需的一個明顯的例子是滾動條,直到現在必須使用第三方包或通過自己實現它來完成。

現在有一個內置的Scrollbar可以直接適合您的應用程序,準確查看滾動條在特定平台中的外觀:有或沒有軌道,可以通過單擊軌道進行滾動,例如,這是如果您希望您的用戶在使用 Flutter 應用程序時從一開始就感到賓至如歸,那麼這將是巨大的。 您還可以對其進行主題化和自定義。

當應用程序的內容可滾動時,看起來 Flutter 在某些時候會自動顯示合適的滾動條。

同時,您可以使用您選擇的滾動條小部件包裝任何可滾動視圖,並創建一個ScrollController以添加為滾動條和可滾動小部件的controller (如果您從未使用過ScrollController ,您可以像TextEditingController一樣使用對於TextField )。 您可以在本文後面的桌面應用程序示例中看到使用常規 Material 滾動條的示例。

Flutter Web 更改

網頁版 Flutter 已經是一種非常可用的形式,但存在性能和可用性問題,這意味著它從來沒有像移動端 Flutter 那樣完美。 隨著 Flutter 2.0 的發布,它有了很多改進,尤其是在性能方面。

編譯目標以前非常實驗性且難以用於渲染您的應用程序(使用 WebAssembly 和 Skia),現在稱為CanvasKit 。 從在移動設備上本地運行 Flutter 應用程序到在瀏覽器中運行它,它已經過改進以提供一致且高性能的體驗。

現在,默認情況下,您的應用程序將為桌面 Web 用戶使用 CanvasKit 呈現,而為移動 Web 用戶使用默認 HTML 渲染器(也有改進,但不如 CanvasKit)。

如果您嘗試使用 Flutter 構建 Web 應用程序,您可能已經註意到擁有像超鏈接這樣簡單的東西並不是特別直觀。 現在,至少,您可以使用Link類創建類似於使用 HTML 時的超鏈接。

這實際上不是 Flutter 本身的新增功能,而是 Google 的url_launcher包最近新增的功能。 您可以在官方 API 參考中找到Link類的完整描述和使用示例。

文本選擇得到了改進,因為現在樞軸點對應於用戶開始選擇文本的位置,而不是相關SelectableText的左邊緣。 此外,現在存在復制/剪切/粘貼選項並且可以正常工作。

儘管如此,文本選擇仍然不是一流的,因為無法在不同的SelectableText小部件中選擇文本,並且可選文本仍然不是默認設置,但我們將討論這一點以及 Flutter web 的其他突出缺點(缺乏 SEO 支持,首先)在本文的結論中。

Flutter 桌面更改

當我去年寫關於使用 Flutter 進行 Web 和桌面開發的文章時,我主要關注的是使用 Flutter 構建 Web 應用程序,因為桌面開發仍然被認為是非常實驗性的(甚至在beta通道上也沒有)。 不過現在,Flutter 桌面支持很快就會跟隨 Web 支持,並且會變得穩定。

性能和穩定性得到了相當大的提升,使用鼠標和鍵盤操作的大型設備的總體可用性的改進使 Web 應用程序受益匪淺,這也意味著 Flutter 桌面應用程序現在更加可用。

桌面應用程序仍然缺乏工具,並且仍然存在許多非常嚴重的未解決的錯誤,因此不要嘗試將它用於您的下一個桌面應用程序項目,該項目旨在公開分發。

使用 Flutter 構建的示例桌面應用程序

Flutter 桌面支持現在已經相當穩定和可用,而且它在未來肯定會變得更好,就像 Flutter 整體上已經變得更好一樣,所以讓我們試試看它的實際效果吧! 您可以在 GitHub 存儲庫上下載整個代碼示例。

我們將構建的應用程序是以下非常簡單的應用程序。 我們有一個側邊欄導航以及每個導航部分的一些內容項。

這就是應用程序的外觀。

首先要做的是弄清楚你的依賴關係

首先,你必須啟用 Flutter 桌面開發,使用命令

flutter config --enable-${OS_NAME}-desktop

您可以將${OS_NAME}替換為您選擇的桌面操作系統, windowslinuxmacos 。 對於此示例,鑑於我們將使用 Ubuntu 主題,我將使用 Linux。

為每個平台構建本機應用程序還需要其他依賴項,例如在 Windows 上需要 Visual Studio 2019,在 macOS 上需要 Xcode 和 CocoaPods,您可以在 Flutter 的官方網站上找到最新的 Linux 依賴項列表。

然後創建一個 Flutter 項目,運行:

 flutter create flutter_ubuntu_desktop_example

然後,我們必須通過將 yaru 添加到yaru中的應用程序dependencies pubspec.yaml (在源代碼樹的根目錄中)來獲取主題本身(我們應用程序的唯一依賴項):

 dependencies: yaru: ^0.0.0-dev.8 flutter: sdk: flutter

然後,讓我們轉到lib/main.dart ,我們的應用程序代碼所在的位置。

首先,我們導入我們需要的東西。 在這種情況下,我們只需要導入常規的 Flutter Material Design 庫和 Yaru 主題(我們將只在本示例中使用 light 主題,因此我們將只show Yaru 包中的一個對象):

 import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart' show yaruLightTheme;

我們將在調用runApp時直接在main中調用MaterialApp構造函數,而不是單獨的應用程序類,這就是我們設置應用程序主題的地方,這將是 Yaru 主題,更具體地說是名為yaruLightTheme的輕主題:

 void main() => runApp(MaterialApp( theme: yaruLightTheme, home: HomePage(), ));

HomePage將是一個StatefulWidget ,保存我們將要顯示的數據,因為它是不可變的(請記住,小部件總是不可變的,可變性在StatefulWidgetState中處理):

 class HomePage extends StatefulWidget { final dataToShow = { "First example data": [ "First string in first list item", "Second in first", "Example", "One" ], "Second example": [ "This is another example", "Check", "It", "Out", "Here's other data" ], "Third example": [ "Flutter is", "really", "awesome", "and", "it", "now", "works", "everywhere,", "this", "is", "incredible", "and", "everyone", "should", "know", "about", "it", "because", "someone", "must", "be", "missing", "out", "on", "a lot" ] }.entries.toList(); @override createState() => HomePageState(); }

HomePageState是我們定義應用程序 UI 和行為的地方。 首先,讓我們看看我們想要構建的小部件樹(列表和網格項目以及間距小部件除外):

應用程序的小部件樹
我們應用程序的計劃小部件樹(沒有間距和放置小部件)。 (大預覽)

我們將使用Container將左側的Column (顯示控件以顯示在應用程序右側的控件)限制為一定的寬度(例如 400 像素),而右側的GridView應該Expanded以填充視圖。

Row的左側(在Column內), ListView應該擴展以填充頂部按鈕Row下方的垂直空間。 在頂部的Row中,我們還需要展開TextButton (重置按鈕)以填充左右 chevron IconButton右側的空間。

完成所有這些操作的結果HomePageState以及根據用戶在左側選擇的內容在右側顯示正確內容的必要邏輯如下:

 class HomePageState extends State<HomePage> { int selected = 0; ScrollController _gridScrollController = ScrollController(); incrementSelected() { if (selected != widget.dataToShow.length - 1) { setState(() { selected++; }); } } decrementSelected() { if (selected != 0) { setState(() { selected--; }); } } @override Widget build(BuildContext context) { return Scaffold( body: Row( children: [ Container( color: Colors.black12, width: 400.0, child: Column( children: [ Row( children: [ IconButton( icon: Icon(Icons.chevron_left), onPressed: decrementSelected, ), IconButton( icon: Icon(Icons.chevron_right), onPressed: incrementSelected, ), Expanded( child: Center( child: TextButton( child: Text("Reset"), onPressed: () => setState(() => selected = 0), ), )) ], ), Expanded( child: ListView.builder( itemCount: widget.dataToShow.length, itemBuilder: (_, i) => ListTile( title: Text(widget.dataToShow[i].key), leading: i == selected ? Icon(Icons.check) : Icon(Icons.not_interested), onTap: () { setState(() { selected = i; }); }, ), ), ), ], )), Expanded( child: Scrollbar( isAlwaysShown: true, controller: _gridScrollController, child: GridView.builder( controller: _gridScrollController, itemCount: widget.dataToShow[selected].value.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 200.0), itemBuilder: (_, i) => Container( width: 200.0, height: 200.0, child: Padding( padding: const EdgeInsets.all(8.0), child: Card( child: Center( child: Text(widget.dataToShow[selected].value[i])), ), ), )), ), ), ], ), ); } }

我們完成了!

然後你構建你的應用程序

flutter build ${OS_NAME}

其中${OS_NAME}是您的操作系統的名稱,與您之前使用flutter config啟用 Flutter 桌面開發的名稱相同。

運行您的應用程序的編譯二進製文件將是

build/linux/x64/release/bundle/flutter_ubuntu_desktop_example

在 Linux 和

build\windows\runner\Release\flutter_ubuntu_desktop_example.exe

在 Windows 上,您可以運行它,您將獲得我在本節開頭向您展示的應用程序。

在 macOS 上,您需要在 Xcode 中打開macos/Runner.xcworkspace ,然後使用 Xcode 構建和運行您的應用程序。

其他顫振變化

還有一些變化也影響了 Flutter 的移動開發,這裡只是其中的一部分。

我們中的許多人,Flutter 開發者,想要的一個功能是更好地支持 Admob 廣告,現在它終於包含在官方的google_mobile_ads包中。 另一種是autocomplete ; 它有一個Autocomplete材料小部件,以及一個更可定制的RawAutocomplete小部件。

我們在關於 Web 開發的部分中討論的Link的添加實際上適用於所有平台,儘管它的效果將最受從事 Flutter Web 項目的人的影響。

最近的 Dart 語言變化

了解影響 Flutter 應用程序開發的 Dart 語言更改非常重要。

特別是 Dart 2.12 帶來了C 語言互操作性支持(Flutter 官網有詳細描述並附有針對不同平台的說明); 此外,穩定的 Dart 發布通道中添加了聲音null-safety

null-safety

Dart 最大的變化是引入了可靠的null-safety ,它得到了越來越多的第三方包以及 Google 開發的庫和包的支持。

Null 安全帶來了編譯器優化並減少了運行時錯誤的機會,因此,即使現在支持它是可選的,重要的是您至少要開始了解如何使您的應用程序為 null 安全。

但目前,這可能不是您的選擇,因為並非所有 Pub 包都是完全空安全的,這意味著如果您的應用程序需要其中一個包,您將無法利用零安全。

使您的應用程序null-safe

如果你曾經使用過 Kotlin,那麼 Dart 的 null 安全方法對你來說會有些熟悉。 查看 Dart 的官方指南,以獲得更完整的 Dart null-safety指南。

您熟悉的所有類型( StringintObjectList 、您自己的類等)現在都不可為空:它們的值永遠不能null

這意味著具有不可為空返回類型的函數必須始終返回一個值,否則您將收到編譯錯誤並且您始終必須初始化不可為空的變量,除非它是一個之前被賦值的局部變量它曾經被使用過。

如果您希望變量可以為空,則需要在類型名稱的末尾添加一個問號,例如在聲明這樣的整數時:

 int? a = 1

在任何時候,您都可以將其設置為null並且編譯器不會為此哭泣。

現在,如果您有一個可以為空的值並將其用於需要不可為空值的東西怎麼辦? 為此,您可以簡單地檢查它是否為空:

 void function(int? a) { if(a != null) { // a is an int here } }

如果您 100%確定變量存在且不為空,則可以使用! 運算符,如下所示:

 String unSafeCode(String? s) => s!;

得出結論:我們可以用 Flutter 2 做什麼?

隨著 Flutter 的不斷發展,我們可以用它做的事情越來越多,但是說 Flutter 可以用於任何類型的應用程序開發項目仍然是不合理的。

在移動端,你不太可能遇到 Flutter 不擅長的東西,因為它從一開始就受到支持並且已經過完善。 你需要的大多數東西都已經在那裡了。

另一方面,網絡和桌面還沒有完全成熟。

桌面仍然有點問題,Windows 應用程序(這是桌面開發的重要組成部分)仍然需要大量工作才能看起來不錯。 僅在某種程度上,Linux 和 macOS 上的情況要好一些。

網絡比桌面更好。 您可以構建體面的 Web 應用程序,但您仍然主要限於單頁應用程序和漸進式 Web 應用程序。 我們仍然肯定不想將它用於需要可索引性和 SEO 的以內容為中心的應用程序。

以內容為中心的應用程序可能不會那麼好,因為文本選擇仍然不是一流的,正如我們在有關 Flutter for web 的當前狀態的部分中看到的那樣。

但是,如果您需要 Flutter 應用程序的 Web 版本,Flutter for the web 可能會很好,特別是因為已經有大量與Web 兼容的包並且列表一直在增長。

其他資源

  • 主題演講(Flutter Engage),YouTube
  • Flutter 2、Flutter、Medium 中的新功能
  • 了解null safety ,Dart.dev
  • 使用 Flutter 進行響應式 Web 和桌面開發,Smashing Magazine
  • 使用 Flutter 解決常見的跨平台問題,Smashing Magazine