Flutter 3.7 新特性:介紹後臺isolate通道

碼裡特別有禪發表於2023-01-30

Flutter 3.7 釋出,本人對其中後臺 isolate 通道比較感興趣,迫不及待翻譯了下Aaron Clarke文章,第一次翻譯,有不足地方歡迎各位大佬們評論區指正,我將持續更新到本文,謝謝。

原文地址:Introducing background isolate channels | by Aaron Clarke | Flutter | Jan, 2023 | Medium

介紹後臺 isolate 通道

https://i.iter01.com/images/ed1cdba1dfd8a31892ccb1b06283b9bd8da485fce5df44ff87af3b704531bfb6.webp

此時此刻,我很高興地宣佈從 Flutter 3.7 開始開發人員可以在任意 isolate 中使用外掛和平臺通道了。 這是自 2018 年以來一直存在並且也是我們排名最高的問題之一。它被降低了優先順序,因為實現並不容易且已存在解決方案,儘管很麻煩:始終在 root isolate(Flutter 提供的 isolate)中使用外掛 . 然而,隨著 Flutter 的日益成熟,越來越關注效能,俗話說“讓它工作,讓它正確,讓它快速”。 選擇實現這一特徵有利於提高效能和易用性。 因此,考慮帶來的收益我們決定實現這一特性。

如果您想了解如何使用此特性,請檢視 GitHub 上的示例程式碼(PS: 原文示例程式碼不可用,這裡我用另外一個官方大佬示例代替了。)。

用例

為什麼有人想在後臺 isolate 中使用外掛呢?很明顯,因為世上並不是所有程式碼都是用 Dart 編寫的。社群多年來一直致力於使用外掛來訪問程式碼(非 Dart 實現),例如 path_provider 找到臨時目錄的能力或 flutter_local_notifications 釋出通知的能力。

另外一個問題是:為什麼有人在後臺執行緒中執行程式碼呢?因為有時您別無選擇,庫可能正呼叫後臺 isolate 回撥,例如 android_alarm_manager_plus。或者某個應用可能正在進行大量計算,而開發人員不希望這些計算影響 UI。

在我幫助谷歌其他團隊使用 Flutter 的過程中,隨著產品的演進,最終會不可避免地遇到 root isolate 瓶頸。 因此,我們需要確保在框架中最佳化,併為開發者提供工具使其在必要時做更少的事。

下面是後臺 isolate 一個人為的用例:

試想,一個應用程式可透過人工智慧根據文字提示生成高解析度影像。使用者之前創作都被儲存在 Firebase Cloud 中,需求是使用者可以用手機隨時分享創作。該 Flutter 應用啟動時會開啟一個後臺 isolate 從 Firebase Cloud Store 下載 8K 文字提示相關圖片,將影像壓縮至指定規格大小匯出,儲存到相簿,最後匯出完成併傳送通知。

在此示例中,後臺 isolate 至少使用了 3 個外掛,一個用於從 Firebase Cloud Storage 中請求資料;接著儲存到手機相簿,儲存完畢傳送本地通知告訴使用者。如果沒有後臺通道,該應用不得不在 root isolate 中複製 8k 影像到後臺 isolate 中進行取樣,當前 Dart 版本沒法保證複製過程時間是不變的。

快速開始

下面是一個使用新 API 在後臺 isolate 中呼叫 shared_preferences 外掛的示例:

import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
 //root isolate傳給後臺isolate標誌
 //(API開始從Flutter3.7)
 RootIsolateToken rootIsolateToken = RootIsolateToken.instance!;
 Isolate.spawn(_isolateMain, rootIsolateToken);
}void _isolateMain(RootIsolateToken rootIsolateToken) async {
 // 將後臺isolate註冊為root isolate
 BackgroundIsolateBinaryMessenger
   .ensureInitialized(rootIsolateToken);
 //你現在可以用shared_preferences外掛了。
 SharedPreferences sharedPreferences =
   await SharedPreferences.getInstance();
 print(sharedPreferences.getBool(‘isDebug’));
}

技術細節

下面是平臺通道工作原理概述:

https://miro.medium.com/max/720/0*Db7Niu7FqKGszecZ

當平臺通道被呼叫產生結果時將透過硬編碼轉到 platform 執行緒。為了保證後臺 isolate 正常執行,傳送訊息的 isolate 應該被持有,以便引擎可以在該 isolate 的事件迴圈上排程結果,這是透過Dart’s ports來實現的,Dart ports 儲存並持有 isolate,這也是透過 C Api 呼叫這些 isolate 的唯一方式。

其他需要實現的功能是將後臺 isolate 與 root isolate 關聯起來。這是令我驚訝的,為了在引擎銷燬時關閉平臺通道,我們應該知道與引擎關聯的後臺 isolate,否則後臺 isolate 可能與正在銷燬引擎通訊,這樣做的效果可以在最終的 API 中看到,必須使用 RootIsolateToken 來初始化BackgroundIsolateBinaryMessenger。

有關實現的更多資訊,請檢視Isolate Platform Channels設計文件。文件中也包含了相左的溝通建議,但尚未付諸實施或接受。

感謝 Flutter 社群的支援,我希望你們都能找到這個新特性更驚豔的用途。

如果覺得文章對你有幫助,點贊、收藏、關注、評論,一鍵四連支援,你的支援就是我創作最大的動力。

❤️ 本文原創聽蟬 公眾號:碼裡特別有禪 歡迎關注原創技術文章第一時間推送 ❤️

相關文章