架构建议与资源
构建可扩展 Flutter 应用的建议。
本页介绍架构最佳实践、其重要性,以及是否建议你在 Flutter 应用中采用。请将这些内容视为建议而非铁律,并根据应用的独特需求加以调整。
本页最佳实践带有优先级,反映 Flutter 团队的推荐力度。
-
强烈推荐: 若你正在新建应用,应始终落实该建议。除非与现有做法根本冲突,否则应认真考虑在既有应用中重构以落实该实践。
-
推荐: 该实践很可能改善你的应用。
-
视情况而定: 该实践在特定情形下可能改善你的应用。
关注点分离
#你应将应用划分为 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. |
数据处理
#谨慎处理数据能让代码更易理解、更少出错,并避免产生畸形或意外的数据。
| 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. |
应用结构
#组织良好的代码既有利于应用本身的健康,也有利于维护代码的团队。
| 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". |
测试
#良好的测试实践使应用更灵活,也让新增逻辑与 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 应用源代码 — 功能完整、健壮的 Flutter 应用源代码,落实了本指南中的许多建议。
very_good_cli — 由 Flutter 专家 Very Good Ventures 制作的 Flutter 应用模板,可生成类似的应用结构。
-
文档
Very Good Engineering 架构文档 — Very Good Engineering 是 VGV 的文档站点,包含技术文章、演示与开源项目,其中包括 Flutter 应用架构相关文档。
-
工具
Flutter 开发者工具 — DevTools 是一套面向 Dart 与 Flutter 的性能与调试工具。
flutter_lints — 包含 Flutter 团队为 Flutter 应用推荐的 lint 规则的软件包,可用于在团队中推广良好编码实践。
反馈
#网站本节内容仍在完善中, 欢迎提供反馈!
除非另有说明,本文档之所提及适用于 Flutter 3.44.0 版本。本页面最后更新时间:2026-06-04。查看文档源码 或者 为本页面内容提出建议。