架构建议与资源
构建可扩展 Flutter 应用的建议。
本页介绍架构最佳实践、其重要性,以及是否建议你在 Flutter 应用中采用。请将这些内容视为建议而非铁律,并根据应用的独特需求加以调整。
本页最佳实践带有优先级,反映 Flutter 团队的推荐力度。
-
强烈推荐: 若你正在新建应用,应始终落实该建议。除非与现有做法根本冲突,否则应认真考虑在既有应用中重构以落实该实践。
-
推荐: 该实践很可能改善你的应用。
-
视情况而定: 该实践在特定情形下可能改善你的应用。
关注点分离
#你应将应用划分为 UI 层与数据层。在各层内部,还应按职责将逻辑进一步拆分到不同类中。
| Recommendation | Description |
|---|---|
| 使用清晰定义的数据层和 UI 层。 Strongly recommend |
关注点分离是最重要的架构原则。数据层向应用的其余部分暴露应用数据,并包含应用中的大部分业务逻辑。 UI 层负责展示应用数据,并监听来自用户的事件。UI 层为 UI 逻辑和 widget 分别使用独立的类。 |
| 在数据层中使用仓库模式 (repository pattern)。 Strongly recommend |
仓库模式是一种软件设计模式,它将数据访问逻辑与应用的其余部分隔离开来。它在应用的业务逻辑与底层数据存储机制(数据库、API、文件系统等)之间创建了一个抽象层。在实践中,这意味着创建 Repository 类和 Service 类。 |
| 在 UI 层中使用 ViewModel 和 View。(MVVM) Strongly recommend |
关注点分离是最重要的架构原则。这种特定的分离能大幅降低代码出错的概率,因为你的 widget 始终保持「被动」(即不含逻辑的 dumb widget)。 |
使用 ChangeNotifier 和 Listenable 处理 widget 更新。
Conditional
|
处理状态管理的选项很多,最终的决定取决于个人偏好。阅读 我们对 ChangeNotifier 的推荐 或 其他流行选项 |
| 不要在 widget 中放置逻辑。 Strongly recommend |
逻辑应当封装在 ViewModel 的方法中。View 唯一应当包含的逻辑是:
|
| 使用领域层 (domain layer)。 Conditional |
只有当你的应用拥有极其复杂的逻辑、以致 ViewModel 变得臃肿,或者你发现自己在多个 ViewModel 中重复编写相同逻辑时,才需要领域层。在超大型应用中,use-case(用例)很有用,但对大多数应用而言,它们只会带来不必要的开销。 适用于具有复杂逻辑需求的应用。 |
数据处理
#谨慎处理数据能让代码更易理解、更少出错,并避免产生畸形或意外的数据。
| Recommendation | Description |
|---|---|
| 使用单向数据流。 Strongly recommend |
数据更新应当只从数据层流向 UI 层。 UI 层中的交互会被发送到数据层进行处理。 |
使用 Commands 处理来自用户交互的事件。Recommend |
Command 能防止应用出现渲染错误,并统一 UI 层向数据层发送事件的方式。你可以在 架构案例研究 中进一步了解 Command。 |
| 使用不可变的数据模型。 Strongly recommend |
不可变数据对于确保任何必要的变更只发生在恰当的位置(通常是数据层或领域层)而言至关重要。由于不可变对象在创建后无法被修改,你必须创建一个新的实例来反映变更。这一过程可以防止 UI 层中的意外更新,并支持清晰的单向数据流。 |
| 使用 freezed 或 built_value 生成不可变的数据模型。 Recommend |
你可以借助一些 package 来为数据模型生成实用的功能,比如 freezed 或 built_value。它们可以生成常见的模型方法,例如 JSON 序列化/反序列化、深度相等性检查以及 copy 方法。如果你的模型数量众多,这些代码生成 package 可能会显著增加应用的构建时间。 |
| 创建相互独立的 API 模型 (API model) 和领域模型 (domain model)。 Conditional |
使用相互独立的模型会增加一些冗余代码,但能避免 ViewModel 和 use-case 变得复杂。 适用于大型应用 |
应用结构
#组织良好的代码既有利于应用本身的健康,也有利于维护代码的团队。
| Recommendation | Description |
|---|---|
| 使用依赖注入。 Strongly recommend |
依赖注入可以避免应用中出现可全局访问的对象,从而降低代码出错的概率。我们推荐你使用 provider package 来处理依赖注入。 |
|
使用 go_router 进行导航。
Recommend
|
对于 90% 的 Flutter 应用,go_router 都是首选的编写方式。 go_router 无法解决某些特定的使用场景,这种情况下,你可以直接使用 Flutter Navigator API,或者尝试 pub.dev 上的其他 package。 |
| 为类、文件和目录使用统一的命名规范。 Recommend |
我们推荐根据类所代表的架构组件来为其命名。例如,你可能会有以下这些类:
为了清晰起见,我们不推荐使用容易与 Flutter SDK 中的对象混淆的名称。例如,你应当把共享的 widget 放在名为 |
| 使用抽象的 Repository 类 Strongly recommend |
Repository 类是应用中所有数据的可信来源 (source of truth),并负责与外部 API 进行通信。创建抽象的 Repository 类让你可以编写不同的实现,以适配不同的应用环境,例如 development(开发)和 staging(预发布)。 |
测试
#良好的测试实践使应用更灵活,也让新增逻辑与 UI 变得直接且低风险。
| Recommendation | Description |
|---|---|
| 为测试创建 fake 对象(并编写能充分利用 fake 的代码)。 Strongly recommend |
fake 对象关注的并不是某个方法的内部实现,而是它的输入和输出。如果你在编写应用代码时牢记这一点,就会促使自己写出模块化、轻量的函数和类,并具备定义良好的输入与输出。 |
推荐资源
#-
代码与模板
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-13。查看文档源码 或者 为本页面内容提出建议。