本指南中的程式碼示例來自指南針示例應用程式,該應用程式可幫助使用者構建和預訂行程。它是一個功能豐富、包含多個功能、路由和螢幕的健壯示例應用程式。該應用程式與 HTTP 伺服器通訊,具有開發和生產環境,包含品牌特有樣式,並且測試覆蓋率高。透過這些以及更多方式,它模擬了一個真實世界的、功能豐富的 Flutter 應用程式。

A screenshot of the splash screen of the compass app.
A screenshot of the home screen of the compass app.
A screenshot of the search form screen of the compass app.
A screenshot of the booking screen of the compass app.

指南針應用程式的架構最接近 Flutter 應用架構指南 中描述的 MVVM 架構模式。本架構案例研究將透過介紹指南針應用程式的“主頁”功能,演示如何實現這些指南。如果您不熟悉 MVVM,應首先閱讀這些指南。

指南針應用程式的主螢幕顯示使用者賬戶資訊以及使用者儲存的行程列表。從此螢幕您可以登出、開啟詳細行程頁面、刪除已儲存的行程,以及導航到核心應用流程的第一頁,該流程允許使用者構建新行程。

在本案例研究中,您將學到以下內容:

本案例研究的編寫順序為:前面的頁面可能會引用後面的頁面。

本案例研究中的程式碼示例包含了理解架構所需的所有細節,但它們不是完整的、可執行的片段。如果您想跟隨完整的應用程式,可以在 GitHub 上找到它。

包結構

#

組織良好的程式碼便於多名工程師協作,最大限度地減少程式碼衝突,並且便於新工程師導航和理解。程式碼組織同時受益於並促進了定義明確的架構。

有兩種流行的程式碼組織方式:

  1. 按功能組織 - 每個功能所需的類將一起分組。例如,您可以有一個 auth 目錄,其中包含 auth_viewmodel.dartlogin_usecase.dartlogout_usecase.dartlogin_screen.dartlogout_button.dart 等檔案。
  2. 按型別組織 - 每種“型別”的架構都將一起分組。例如,您可以擁有 repositoriesmodelsservicesviewmodels 等目錄。

本指南推薦的架構傾向於結合這兩種方式。資料層物件(儲存庫和服務)不與單個功能繫結,而 UI 層物件(檢視和檢視模型)則繫結。以下是 Compass 應用程式中程式碼的組織方式。

lib
├─┬─ ui
│ ├─┬─ core
│ │ ├─┬─ ui
│ │ │ └─── <shared widgets>
│ │ └─── themes
│ └─┬─ <FEATURE NAME>
│   ├─┬─ view_model
│   │ └─── <view_model class>.dart
│   └─┬─ widgets
│     ├── <feature name>_screen.dart
│     └── <other widgets>
├─┬─ domain
│ └─┬─ models
│   └─── <model name>.dart
├─┬─ data
│ ├─┬─ repositories
│ │ └─── <repository class>.dart
│ ├─┬─ services
│ │ └─── <service class>.dart
│ └─┬─ model
│   └─── <api model class>.dart
├─── config
├─── utils
├─── routing
├─── main_staging.dart
├─── main_development.dart
└─── main.dart

// The test folder contains unit and widget tests
test
├─── data
├─── domain
├─── ui
└─── utils

// The testing folder contains mocks other classes need to execute tests
testing
├─── fakes
└─── models

大部分應用程式程式碼位於 datadomainui 資料夾中。data 資料夾按型別組織程式碼,因為儲存庫和服務可以在不同功能之間以及被多個檢視模型使用。ui 資料夾按功能組織程式碼,因為每個功能只有一個檢視和一個檢視模型。

此資料夾結構的其它值得注意的特點:

  • UI 資料夾還包含一個名為“core”的子目錄。Core 包含由多個檢視共享的 widget 和主題邏輯,例如帶有品牌樣式的按鈕。
  • domain 資料夾包含應用程式資料型別,因為它們被資料層和 UI 層使用。
  • 該應用程式包含三個“main”檔案,它們充當應用程式用於開發、暫存和生產的不同入口點。
  • 在與 lib 同一級別存在兩個與測試相關的目錄:test/ 包含測試程式碼,並且其結構與 lib/ 匹配。testing/ 是一個子包,其中包含可用於其他包測試程式碼的 mock 和其他測試實用程式。testing/ 資料夾可以被描述為您不釋出的應用程式的一個版本。它是被測試的內容。

指南針應用程式中還有其他與架構無關的程式碼。要檢視完整的包結構,請在 GitHub 上檢視

其他架構選項

#

本案例研究中的示例演示了一個應用程式如何遵守我們推薦的架構規則,但也可以編寫許多其他示例應用程式。此應用程式的 UI 嚴重依賴於檢視模型和 ChangeNotifier,但也可以輕鬆地使用 stream 或由 riverpodflutter_blocsignals 包提供的其他庫來編寫。此應用程式層之間的通訊透過方法呼叫處理所有內容,包括輪詢新資料。它也可以選擇使用 stream 從儲存庫向檢視模型公開資料,並且仍然遵守本指南涵蓋的規則。

即使您嚴格遵循本指南,並且選擇不引入其他庫,您仍然需要做出決定:您是否會有一個域層?如果是,您將如何管理資料訪問?答案很大程度上取決於單個團隊的需求,因此沒有唯一的正確答案。無論您如何回答這些問題,本指南中的原則都將幫助您編寫可擴充套件的 Flutter 應用程式。

如果您仔細觀察,難道所有的架構不都是 MVVM 嗎?

反饋

#

隨著本網站的這一部分不斷發展,我們歡迎您的反饋