架構建議與資源
建立可擴展 Flutter 應用程式的建議。
本頁介紹架構最佳實踐、其重要性,以及我們是否建議你在 Flutter 應用程式中採用這些做法。 你應將這些建議視為參考,而非絕對規則,並根據你應用程式的獨特需求進行調整。
本頁的最佳實踐會標註優先級,這反映了 Flutter 團隊對該建議的推薦程度。
- 強烈建議: 如果你正在開始建立新應用程式,應始終實作此建議。除非與你現有的架構方式根本衝突,否則也應強烈考慮將現有應用程式重構以實現此做法。
- 建議: 採用此做法很可能會提升你的應用程式品質。
- 視情況而定: 在特定情境下,此做法可以改善你的應用程式。
關注點分離 {#separation-of-concerns}
#你應將應用程式分為 UI 層與資料層。在這些層中, 你應進一步依職責將邏輯拆分為不同類別。
| Recommendation | Description |
|---|---|
| Use clearly defined data and UI layers. Strongly recommend |
Separation of concerns is the most important architectural principle. The data layer exposes application data to the rest of the app, and contains most of the business logic in your application. The UI layer displays application data and listens for user events from users. The UI layer contains separate classes for UI logic and widgets. |
| Use the repository pattern in the data layer. Strongly recommend |
The repository pattern is a software design pattern that isolates the data access logic from the rest of the application. It creates an abstraction layer between the application's business logic and the underlying data storage mechanisms (databases, APIs, file systems, etc.). In practice, this means creating Repository classes and Service classes. |
|
Use ViewModels and Views in the UI layer. (MVVM)
Strongly recommend
|
Separation of concerns is the most important architectural principle. This particular separation makes your code much less error prone because your widgets remain "dumb". |
Use ChangeNotifiers and Listenables to handle widget updates.
Conditional
|
The There are many options to handle state-management, and ultimately the decision comes down to personal preference. Read about our ChangeNotifier recommendation or other popular options. |
| Do not put logic in widgets. Strongly recommend |
Logic should be encapsulated in methods on the ViewModel. The only logic a view should contain is:
|
| Use a domain layer. Conditional |
A domain layer is only needed if your application has exceeding complex logic that crowds your ViewModels, or if you find yourself repeating logic in ViewModels. In very large apps, use-cases are useful, but in most apps they add unnecessary overhead. Use in apps with complex logic requirements. |
資料處理 {#handling-data}
#謹慎處理資料能讓程式碼更易於理解、降低錯誤發生機率, 並防止產生格式錯誤或非預期的資料。
| Recommendation | Description |
|---|---|
| Use unidirectional data flow. Strongly recommend |
Data updates should only flow from the data layer to the UI layer. Interactions in the UI layer are sent to the data layer where they're processed. |
Use Commands to handle events from user interaction.
Recommend
|
Commands prevent rendering errors in your app, and standardize how the UI layer sends events to the data layer. Read about commands in the architecture case study. |
| Use immutable data models. Strongly recommend |
Immutable data is crucial in ensuring that any necessary changes occur only in the proper place, usually the data or domain layer. Because immutable objects can't be modified after creation, you must create a new instance to reflect changes. This process prevents accidental updates in the UI layer and supports a clear, unidirectional data flow. |
|
Use freezed or built_value to generate immutable data models.
Recommend
|
You can use packages to help generate useful functionality in your data models, freezed or built_value. These can generate common model methods like JSON ser/des, deep equality checking and copy methods. These code generation packages can add significant build time to your applications if you have a lot of models. |
| Create separate API models and domain models. Conditional |
Using separate models adds verbosity, but prevents complexity in ViewModels and use-cases. Use in large apps. |
應用程式結構 {#app-structure}
#組織良好的程式碼對應用程式本身的健全性及開發團隊都有所助益。
| Recommendation | Description |
|---|---|
| Use dependency injection. Strongly recommend |
Dependency injection prevents your app from having globally accessible objects, which makes your code less error prone. We recommend you use the provider package to handle dependency injection. |
|
Use go_router for navigation.
Recommend
|
Go_router is the preferred way to write 90% of Flutter applications. There are some specific use-cases that go_router doesn't solve, in which case you can use the Flutter Navigator API directly or try other packages found on pub.dev. |
|
Use standardized naming conventions for classes, files and directories.
Recommend
|
We recommend naming classes for the architectural component they represent. For example, you may have the following classes:
For clarity, we do not recommend using names that can be confused with objects from the Flutter SDK.
For example, you should put your shared widgets in a directory called |
| Use abstract repository classes Strongly recommend |
Repository classes are the sources of truth for all data in your app, and facilitate communication with external APIs. Creating abstract repository classes allows you to create different implementations, which can be used for different app environments, such as "development" and "staging". |
測試 {#testing}
#良好的測試實踐讓你的應用程式更具彈性。 同時也能讓新增邏輯與 UI 的過程更簡單、風險更低。
| Recommendation | Description |
|---|---|
|
Test architectural components separately, and together.
Strongly recommend
|
|
|
Make fakes for testing (and write code that takes advantage of fakes.)
Strongly recommend
|
Fakes aren't concerned with the inner workings of any given method as much as they're concerned with inputs and outputs. If you have this in mind while writing application code, you're forced to write modular, lightweight functions and classes with well defined inputs and outputs. |
推薦資源
#-
程式碼與範本
- Compass app source code - 一個功能完整且健壯的 Flutter 應用程式原始碼,實作了許多本頁建議。
- very_good_cli - 由 Flutter 專家 Very Good Ventures 製作的 Flutter 應用程式範本。 此範本會產生類似的應用程式結構。
-
文件
- Very Good Engineering architecture documentation - Very Good Engineering 是 VGV 經營的文件網站,包含技術文章、展示與開源專案。 其中也有關於 Flutter 應用程式架構的文件。
-
工具
- Flutter developer tools - DevTools 是一套針對 Dart 與 Flutter 的效能與除錯工具。
- flutter_lints - 由 Flutter 團隊推薦的 Flutter 應用程式檢查規則套件。 使用此套件可促進團隊間良好的程式撰寫習慣。
意見回饋
#由於本網站此區塊仍在持續演進中, 我們歡迎你的意見回饋!
Unless stated otherwise, the documentation on this site reflects Flutter 3.44.0. Page last updated on 2026-06-14. View source or report an issue.