架构案例研究
一个 Flutter 应用的演练,该应用实现了 MVVM 架构模式。
本指南中的代码示例来自 Compass 示例应用程序,该应用程序帮助用户构建和预订行程。它是一个功能丰富、包含许多功能、路由和屏幕的健壮示例应用程序。该应用程序与 HTTP 服务器通信,具有开发和生产环境,包含特定于品牌的样式,并包含高测试覆盖率。在这些方面以及更多方面,它模拟了一个真实世界、功能丰富的 Flutter 应用程序。




Compass 应用程序的架构最类似于 Flutter 应用架构指南 中描述的 MVVM 架构模式。本架构案例研究通过演练 Compass 应用程序的“主页”功能来演示如何实施这些指南。如果您不熟悉 MVVM,则应先阅读这些指南。
Compass 应用程序的主屏幕显示用户帐户信息和用户保存的行程列表。从此屏幕您可以注销、打开详细的行程页面、删除保存的行程以及导航到核心应用程序流程的第一页,该页面允许用户构建新的行程。
在本案例研究中,您将学习以下内容
- 如何使用存储库和服务在 数据层 中以及在 UI 层 中使用 MVVM 架构模式来实现 Flutter 的 应用架构指南
- 如何使用 命令模式 来安全地渲染数据更改时的 UI
- 如何使用
ChangeNotifier和Listenable对象来管理状态 - 如何使用
package:provider实现 依赖注入 - 如何 设置测试 以遵循推荐的架构
- 大型 Flutter 应用程序的有效 包结构
本案例研究旨在按顺序阅读。任何给定页面都可能引用前面的页面。
本案例研究中的代码示例包含理解架构所需的所有详细信息,但它们不是完整的、可运行的代码片段。如果您希望与完整的应用程序一起使用,可以在 GitHub 上找到它。
包结构
#组织良好的代码更容易让多个工程师在代码冲突最少的情况下进行协作,并且更容易让新工程师导航和理解。代码组织既受益于明确定义的架构,也促进了明确定义的架构。
组织代码有两种流行的方法
- 按功能 - 每个功能所需的类组合在一起。例如,您可能有一个
auth目录,其中包含诸如auth_viewmodel.dart、login_usecase.dart、logout_usecase.dart、login_screen.dart、logout_button.dart等文件。 - 按类型 - 将每种“类型”的架构组合在一起。例如,您可能拥有诸如
repositories、models、services和viewmodels之类的目录。
本指南中推荐的架构同时结合了这两种方法。数据层对象(存储库和服务)不与单个功能绑定,而 UI 层对象(视图和视图模型)是绑定的。以下是代码在 Compass 应用程序中组织的方式。
-
lib/
ui/
core/
ui/
- <shared_widgets>
- themes/
<feature_name>/
view_models/
- <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
-
test/// 包含单元和组件测试。
- data/
- domain/
- ui/
- utils/
-
testing/// 包含其他类需要执行测试的模拟对象。
- fakes/
- models/
大多数应用程序代码位于 data、domain 和 ui 文件夹中。data 文件夹按类型组织代码,因为存储库和服务可以在不同的功能中使用,并且可以被多个视图模型使用。ui 文件夹按功能组织代码,因为每个功能恰好有一个视图和一个视图模型。
此文件夹结构的其它值得注意的特性
- UI 文件夹还包含一个名为“core”的子目录。Core 包含由多个视图共享的小部件和主题逻辑,例如具有品牌样式的按钮。
- domain 文件夹包含应用程序数据类型,因为它们由数据和 UI 层使用。
- 该应用程序包含三个“main”文件,它们充当开发、暂存和生产应用程序的不同入口点。
- 在与
lib同一级别有两个与测试相关的目录:test/包含测试代码,其自身结构与lib/匹配。testing/是一个子包,包含可以在其他包的测试代码中使用的模拟对象和其他测试实用程序。testing/文件夹可以被描述为您的应用程序的一个版本,您不会发布它。它是被测试的内容。
Compass 应用程序中还有一些与架构无关的其他代码。有关完整的包结构,请 在 GitHub 上查看。
其他架构选项
#本案例研究中的示例演示了一个应用程序如何遵守我们推荐的架构规则,但可以编写许多其他示例应用程序。此应用程序的 UI 严重依赖视图模型和 ChangeNotifier,但也可以使用流或像 riverpod、flutter_bloc 和 signals 包提供的其他库编写。此应用程序中层与层之间的通信使用方法调用处理所有内容,包括轮询新数据。它还可以使用流将存储库中的数据暴露给视图模型,同时仍然遵守本指南中涵盖的规则。
即使您完全遵循本指南,并且不引入其他库,您仍然需要做出决定:您是否会有一个域层?如果是,您将如何管理数据访问?答案在很大程度上取决于单个团队的需求,因此没有唯一的正确答案。无论您如何回答这些问题,本指南中的原则都将帮助您编写可扩展的 Flutter 应用程序。
而且,如果您眯起眼睛看,所有架构最终都是 MVVM 吗?
反馈
#由于本网站的这一部分正在不断发展,我们 欢迎您的反馈!