跳到主內容

架構建議與資源

構建可擴充套件 Flutter 應用的建議。

本頁面介紹了架構最佳實踐、它們的重要性,以及我們是否建議在你的 Flutter 應用中使用它們。請將這些建議視為參考而非死板的規則,你應該根據應用的具體需求進行適配。

本頁面上的最佳實踐設有優先順序,反映了 Flutter 團隊推薦它們的強烈程度。

  • 強烈推薦:如果你正在構建一個新應用,應該始終採用此建議。對於現有應用,除非實施該實踐會與你當前的開發方式產生根本性衝突,否則應認真考慮進行重構以採用它。
  • 推薦:該實踐很可能會改善你的應用。
  • 視情況而定:該實踐在特定情況下可以改善你的應用。

關注點分離

#

你應該將應用拆分為 UI 層和資料層。在這些層級內,應進一步按照職責將邏輯拆分到不同的類中。

建議描述
使用明確定義的資料層和 UI 層。
強烈推薦

關注點分離是架構最重要的原則。資料層嚮應用的其餘部分公開應用資料,幷包含應用中大部分的業務邏輯。UI 層顯示應用資料並監聽使用者的事件。UI 層包含用於 UI 邏輯和 Widget 的單獨類。

在資料層使用儲存庫(Repository)模式。
強烈推薦

儲存庫模式是一種軟體設計模式,它將資料訪問邏輯與應用的其餘部分隔離開來。它在應用的業務邏輯和底層資料儲存機制(資料庫、API、檔案系統等)之間建立了一個抽象層。在實踐中,這意味著要建立 Repository 類和 Service 類。

在 UI 層使用 ViewModel 和 View。(MVVM)
強烈推薦

關注點分離是架構最重要的原則。這種特定的分離方式使程式碼出錯率大大降低,因為你的 Widget 保持為“啞(dumb)”元件。

使用 ChangeNotifierListenable 來處理 Widget 更新。
視情況而定

ChangeNotifier API 是 Flutter SDK 的一部分,是一種讓 Widget 觀察 ViewModel 變化的便捷方式。

有很多選項可以處理狀態管理,最終的決定取決於個人喜好。閱讀我們的 ChangeNotifier 建議其他熱門選項

不要在 Widget 中編寫邏輯。
強烈推薦

邏輯應封裝在 ViewModel 的方法中。View 中唯一可以包含的邏輯是:

  • 簡單的 if 語句,用於根據 ViewModel 中的標誌或可空欄位顯示和隱藏 Widget
  • 依賴於 Widget 進行計算的動畫邏輯
  • 基於裝置資訊(如螢幕尺寸或方向)的佈局邏輯。
  • 簡單的路由邏輯
使用領域(Domain)層。
視情況而定

只有當你的應用具有極其複雜的邏輯,導致 ViewModel 變得臃腫,或者你發現自己在 ViewModel 中重複編寫邏輯時,才需要使用領域層。在超大型應用中,用例(Use-cases)很有用,但在大多數應用中,它們會增加不必要的開銷。

用於具有複雜邏輯需求的應用。

處理資料

#

謹慎處理資料可以使程式碼更易於理解、減少錯誤,並防止建立格式錯誤或意外的資料。

建議描述
使用單向資料流。
強烈推薦

資料更新應僅從資料層流向 UI 層。UI 層中的互動被髮送到資料層進行處理。

使用 Command 處理來自使用者互動的事件。
推薦

Command 可以防止應用中的渲染錯誤,並標準化 UI 層向資料層傳送事件的方式。閱讀 架構案例研究 中關於 Command 的內容。

使用不可變(Immutable)資料模型。
強烈推薦

不可變資料對於確保必要的更改僅發生在正確的地方(通常是資料層或領域層)至關重要。由於不可變物件在建立後無法修改,因此必須建立新例項來反映更改。此過程可防止 UI 層中的意外更新,並支援清晰的單向資料流。

使用 freezed 或 built_value 生成不可變資料模型。
推薦

你可以使用軟體包來幫助生成資料模型中的有用功能,例如 freezedbuilt_value。它們可以生成常見的模型方法,如 JSON 序列化/反序列化、深度相等性檢查和複製方法。如果你有大量的模型,這些程式碼生成包可能會顯著增加應用的構建時間。

建立單獨的 API 模型和領域模型。
視情況而定

使用單獨的模型會增加冗餘,但能防止 ViewModel 和用例中出現複雜性。

用於大型應用。

應用結構

#

組織良好的程式碼既有益於應用本身的健康,也有益於參與開發該程式碼的團隊。

建議描述
使用依賴注入。
強烈推薦

依賴注入可以防止應用擁有全域性可訪問的物件,從而降低程式碼的出錯率。我們建議使用 provider 軟體包來處理依賴注入。

使用 go_router 進行導航。
推薦

Go_router 是 90% 的 Flutter 應用的首選方案。有些特定的用例 go_router 無法解決,在這種情況下,你可以直接使用 Flutter Navigator API 或嘗試 pub.dev 上的其他軟體包。

使用標準化的類、檔案和目錄命名約定。
推薦

我們建議按照架構元件所代表的含義來命名類。例如,你可能會有以下類:

  • HomeViewModel
  • HomeScreen
  • UserRepository
  • ClientApiService

為了清晰起見,我們不建議使用容易與 Flutter SDK 物件混淆的名稱。例如,你應該將共享 Widget 放在名為 ui/core/ 的目錄中,而不是名為 /widgets 的目錄中。

使用抽象 Repository 類
強烈推薦

Repository 類是應用中所有資料的真實來源,並促進與外部 API 的通訊。建立抽象 Repository 類允許你建立不同的實現,這些實現可用於不同的應用環境,例如“開發”和“預釋出”。

測試

#

良好的測試實踐使應用更靈活。它還使得新增新邏輯和新 UI 變得簡單且風險較低。

建議描述
分別測試和組合測試架構元件。
強烈推薦
  • 為每個 Service、Repository 和 ViewModel 類編寫單元測試。這些測試應單獨測試每個方法的邏輯。
  • 為 View 編寫 Widget 測試。測試路由和依賴注入尤為重要。
建立測試用的模擬物件(Fake),並編寫利用模擬物件的程式碼。
強烈推薦

模擬物件(Fake)並不關心給定方法的內部工作原理,它們更關心輸入和輸出。如果在編寫應用程式碼時考慮到這一點,你將被迫編寫具有明確輸入和輸出的模組化、輕量級的函式和類。

推薦資源

#
  • 程式碼與模板
    • Compass 應用原始碼 - 一個功能齊全、健壯的 Flutter 應用的原始碼,實現了許多這些建議。
    • very_good_cli - 由 Flutter 專家 Very Good Ventures 製作的 Flutter 應用模板。該模板生成了類似的應用程式結構。
  • 文件
    • Very Good Engineering 架構文件 - Very Good Engineering 是 VGV 推出的文件站點,包含技術文章、演示和開源專案。它包括有關架構 Flutter 應用的文件。
  • 工具
    • Flutter 開發者工具 (DevTools) - DevTools 是用於 Dart 和 Flutter 的一套效能和除錯工具。
    • flutter_lints - 一個包含 Flutter 團隊推薦的 Flutter 應用 Lint 規則的軟體包。使用此軟體包可以在團隊中鼓勵良好的編碼實踐。

反饋

#

由於本網站的這一部分正在不斷完善中,我們歡迎你的反饋