Dart 2.17 現已發佈: 工作效率與平臺集成

作者 / Michael Thomsen, Product Manager working on Dart and Flutter

我們在 Google I/O 大會上發佈了全新的 2.17 版 Dart SDK。此版本構建於我們的核心主題之上,即領先的工作效率與平臺可移植性。Dart 2.17 帶來了新的語言特性,包括在枚舉中支持成員變量、改進超類參數繼承及提高命名參數的靈活性等。我們推出全新的主要版本 package:lints 來幫助大家根據最佳實踐檢查 Dart 代碼。同時,我們還大幅更新了核心庫的 API 文檔,爲其帶來了豐富的代碼示例。爲了改善平臺集成效果,我們在 Flutter 插件中提供了新的模版,以便使用 dart:ffi 與原生平臺進行 C 語言的互操作,還開始爲 RISC-V 處理器提供實驗性支持,以及爲 macOS 和 Windows 可執行文件提供簽名。

新語言特性助力工作效率提升

爲了幫助開發者提升工作效率,我們一直在改進 Dart 語言,爲其添加新特性並持續改進現有功能。Dart 2.17 新增對枚舉成員變量的支持,優化在構造函數中使用命名參數的方式,並使超類參數的繼承更加便捷,減少了冗長和重複的代碼。

在枚舉中支持成員變量

枚舉非常適合用來表示一組離散的狀態。例如,我們可以將水描述爲 enum Water { frozen, lukewarm, boiling }。但是,如果我們想在 enum 上添加一些方法,例如,將每個狀態轉換爲溫度,以及支持將 enum 轉換爲 String,該怎麼辦?或許我們可以使用擴展方法來添加一個 waterToTemp() 方法,但必須注意讓其與 enum 保持同步。對於 String 轉換,我們希望重寫 toString(),但這個做法在之前的版本不受支持。

Dart 2.17 中現已全面支持枚舉成員變量。因此,我們可以添加保存狀態的字段、設置狀態的構造函數、具備功能的方法,甚至重寫現有方法。許多開發者對此功能一直有需求,這是我們語言問題跟蹤專頁中 投票排名第三的問題

再次以水爲例,我們可以添加一個保存溫度的 int 字段,並添加一個接收 int的默認構造函數:

enum Water {
…
 final int tempInFahrenheit;
 const Water(this.tempInFahrenheit);
}

爲了確保在創建 enum 時構造函數被調用,我們需要爲每一個 enum 值進行調用:

enum Water {
 frozen(32),
 lukewarm(100),
 boiling(212);
…
}

要支持轉換爲 String,我們只需重寫 enums 繼承自 ObjecttoString 方法:

@override
String toString() => "The $name water is $tempInFahrenheit F.";

這樣即可獲得一個可以輕鬆實例化的完整 enum,您可以在其上調用方法:

void main() {
 print(Water.frozen); // Prints “The frozen water is 32 F.”
}

以下爲這兩種方法的完整示例。不難看出,全新 Dart 2.17 版本的代碼更加易於閱讀和維護。

超類初始化構造

如果您的代碼存在類繼承層次結構,常見模式是將一些構造函數參數傳遞給超類的構造函數。爲此,子類需要 1) 在其構造函數中列出每個參數;2) 使用這些參數調用超類的構造函數。這樣會導致樣板代碼反覆出現,從而增加代碼的閱讀和維護難度。

在幾位 Dart 社區成員的幫助下,我們的改進目標得以實現。半年前,GitHub 用戶 @roy-sianez 提交了一個相關的 語言問題。他的建議與 GitHub 用戶 @apps-transround 之前提出的建議 類似: 也許我們可以這樣解決問題,即引入新的構造方式,來表示超類中已指定一個參數。我們認爲這個想法不錯,所以將其添加在 Dart 2.17 中。從下面的示例中不難看出,這尤其與 Flutter widget 代碼密切相關。實際上,在我們將這項新特性應用到 Flutter 框架後,代碼總共 減少了近兩千行

在任意參數位置使用命名參數

最後,我們改進了調用某個方法時命名參數的使用方式。此前,命名參數只能出現在方法參數列表的最後。如果您希望讓位置參數靠後,從而提升代碼可讀性,這種限制就會令人感到非常煩惱。以下面 List<T>.generate 構造函數的調用爲例: 之前,growable 參數必須放在最後,因爲它位於含生成器的大型位置參數之後,很容易在閱讀時被錯過。而現在,您可以根據喜好排列參數,先放置小型命名參數,最後再放置帶生成器的參數。

更多有關這三個特性的示例,請參閱我們更新的 枚舉超類初始化構造命名參數 示例代碼。

工作效率工具

在工作效率主題方面,我們對核心工具進行了一些改進。

在 Dart 2.14 中,我們引入了 package:lints,它可與 Dart 分析器一起工作,以幫助您避免編寫出包含錯誤的 Dart 代碼,並通過規範化的方式提升代碼審覈效率。後來分析器中又新增了許多 Lint,我們對其進行了仔細分類,並從中選擇了 10 條新的 Lint 用於所有 Dart 代碼,還有 2 條新的 Lint 專門用於 Flutter 代碼。其中一些 Lint 可確保 pubspec 文件中包含導入內容,防止濫用類型參數空檢查,以及保證子屬性格式一致。您可以通過簡單的命令升級到新的 Lint:

  • Dart package 可以使用:

    dart pub upgrade —-major-versions lints
    
  • Flutter package 可以使用:

    flutter pub upgrade —-major-versions flutter_lints
    

SecureSockets 通常用於啓用受 TLS 和 SSL 保護的 TCP 套接字。Dart 2.17 發佈之前,由於無法檢查安全數據流量,開發過程中調試這些套接字非常困難。現在我們添加了指定 keyLog 文件的功能。指定日誌文件後,與服務器交換新的 TLS 密鑰時,一行 NSS 密鑰日誌格式 的文本就會附加到文件中。這樣,網絡流量分析工具 (如 Wireshark) 即可解密通過套接字發送的內容。更多詳細信息,請參閱 SecureSocket.connect()API 文檔

dart doc 工具生成的 API 文檔是大多數 Dart 開發者學習新 API 的重要資源之一。儘管我們的 核心庫 API 一直都有詳實的文本描述,但許多開發者告訴我們,他們更喜歡通過閱讀示例代碼來學習 API。在 Dart 2.17 中,我們徹底檢查了所有主要的核心庫,爲瀏覽量排在前 200 名的頁面添加了詳實的示例代碼。您可以對比 Dart 2.16Dart 2.17 中 dart:convert 的文檔頁面,希望這些更新有助於您更輕鬆地使用 API 文檔。

爲平臺新增功能可以提升工作效率,清理堆積的既有問題,並刪除棄用的功能同樣也可以。這樣做有助於保持精簡的使用體驗,對新上手的開發者而言,這一點尤爲重要。爲此,我們從 dart:io 庫中刪除了 231 行已棄用的代碼。如果您仍在使用這些已棄用的 API,可以使用 dart fix 進行修復和替換。我們還在繼續努力刪除 已棄用的 Dart CLI 工具,此外,本次更新刪除了 dartdoc 工具 (使用 dart doc 代替) 和 pub 工具 (使用 dart pubflutter pub 代替)。

擴大平臺集成與支持

平臺集成與支持是我們的第二個核心主題。Dart 是一種真正的多平臺語言。儘管我們現已支持 大量平臺,但仍在不斷拓展演進,確保您可以與每個受支持的平臺深度集成,同時也支持新出現的平臺。

Dart FFI 是我們 與 C 語言或原生代碼互操作 的核心機制,廣泛用於將 Dart 代碼與現有原生平臺代碼集成。在 Flutter 上,Dart FFI 也是構建使用託管平臺原生 API (例如 Windows win32 API) 的 插件 的理想方法。在 Dart 2.17 和 Flutter 3 中,我們爲 flutter 工具添加了模板,現在您可以輕鬆地創建 FFI 插件,這些插件的 Dart API 通過 dart:ffi 調用原生代碼。詳細信息請參閱官方文檔中的 "開發 package 和插件"。

爲支持在具有 ABI (應用程序二進制接口) 特有類型的平臺上使用 FFI,FFI 現已支持 ABI 特有類型。例如,現在您可以使用 Long (C 語言中的 long) 正確表示 ABI 特有大小的長整數,由於 CPU 架構的區別,結果可能是 32 位或 64 位。有關支持類型的完整列表,請參閱 AbiSpecificInteger API 頁面中的 "Implementers" 列表。

在使用 Dart FFI 與原生平臺深度集成時,有時開發者需要調整適配 Dart 代碼和原生代碼的內存或其他資源 (端口、文件等) 的清理行爲。長期以來,這個問題都十分棘手,因爲 Dart 是一種會自動處理清理行爲的垃圾回收語言。在 Dart 2.17 中,我們通過引入 Finalizer 的概念,解決了這個問題。Finalizer 中包括一個 Finalizable 標記接口,用於 "標記" 不應過早終結或丟棄的對象,以及一個可以附加到 Dart 對象的 NativeFinalizer 類,在對象即將被垃圾回收時提供回調運行。這樣,在原生代碼和 Dart 代碼中都可以運行清理代碼。更多詳細信息,請參閱 NativeFinalizer API 文檔,或參閱 WeakReferenceFinalizer 文檔中的描述和示例,以瞭解常規 Dart 代碼中的類似做法。

支持將 Dart 編譯爲原生代碼,是使 Flutter 應用具有出色啓動性能和快速渲染能力的核心要素。除此之外,您還可以使用 dart compile 將 Dart 文件編譯爲可執行文件。這些可執行文件可以在任何機器上獨立運行,無需安裝 Dart SDK。Dart 2.17 中的另一個新功能是支持 對可執行文件進行簽名,從而在往往需要簽名的 Windows 和 macOS 上進行部署。

我們還在積極跟進新平臺的發展,不斷擴大可支持的平臺範圍。RISC-V 是一個全新的處理器指令集。RISC-V International 是一家全球非營利性組織,其擁有 RISC-V 規範並使該指令集保持自由開放的狀態。儘管仍是新平臺,但其潛力無限,因此我們的 2.17.0–266.1.beta Linux 版本 (以後可能進入我們的 beta 渠道) 中已經爲其提供了實驗性的支持。我們希望能夠獲得您的反饋,請大家不吝 提出問題分享使用體驗

即刻使用 Dart 2.17!

我們希望 Dart 2.17 版本能打動您,並能助力您提高工作效率,把您的應用帶去更多平臺。您可以即刻下載 Dart 2.17 並開始使用,或者使用 Flutter 3 SDK 中包含的 Dart SDK。

別忘了觀看 Google I/O 大會中 Flutter 的最新內容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章