Skip to main content

架构建议和资源

本页面介绍了架构最佳实践、其重要性以及我们是否建议您在 Flutter 应用中使用它们。您应将这些建议视为建议,而非一成不变的规则,并应根据您应用的独特需求对其进行调整。

本页面上的最佳实践具有优先级,这反映了 Flutter 团队推荐的强烈程度。

  • **强烈推荐:**如果您开始构建新的应用程序,则应始终实施此建议。除非这样做会与您当前的方法发生根本冲突,否则您应强烈考虑重构现有应用程序以实施此实践。
  • **推荐:**此实践可能会改进您的应用程序。
  • **有条件的:**此实践在某些情况下可以改进您的应用程序。

Separation of concerns

You should separate your app into a UI layer and a data layer. Within those layers, you should further separate logic into classes by responsibility.




建议描述

Use clearly defined data and UI layers.

强烈推荐

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.

强烈推荐

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)

强烈推荐

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.

有条件的

The ChangeNotifier API is part of the Flutter SDK, and is a convenient way to have your widgets observe changes in your ViewModels.


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.

强烈推荐

Logic should be encapsulated in methods on the ViewModel. The only logic a view should contain is:

  • Simple if-statements to show and hide widgets based on a flag or nullable field in the ViewModel

  • Animation logic that relies on the widget to calculate

  • Layout logic based on device information, like screen size or orientation.

  • Simple routing logic


Use a domain layer.

有条件的

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

Handling data with care makes your code easier to understand, less error prone, and prevents malformed or unexpected data from being created.





建议描述

Use unidirectional data flow.

强烈推荐

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.

推荐

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.

强烈推荐

Immutable data is crucial in making sure that data only updates in the model.


Use freezed or built_value to generate immutable data models.

推荐

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.

有条件的

Using separate models adds verbosity, but prevents complexity in ViewModels and use-cases.


Use in large apps.


App structure

Well organized code benefits both the health of the app itself, and the team working on the code.




建议描述

Use dependency injection.

强烈推荐

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.

推荐

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.

推荐

We recommend naming classes for the architectural component they represent. For example, you may have the following classes:

  • HomeViewModel
  • HomeScreen
  • UserRepository
  • ClientApiService

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 ui/core/, rather than a directory called /widgets.


Use abstract repository classes

强烈推荐

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

Good testing practices makes your app flexible. It also makes it straightforward and low risk to add new logic and new UI.

建议描述

Test architectural components separately, and together.

强烈推荐

* Write unit tests for every service, repository and ViewModel class. These tests should test the logic of every method individually.

  • Write widget tests for views. Testing routing and dependency injection are particularly important.


Make fakes for testing (and write code that takes advantage of fakes.)

强烈推荐

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.



推荐资源

#
  • 代码和模板
    • 指南针应用源代码 - 一个功能齐全、健壮的 Flutter 应用程序的源代码,它实现了许多这些建议。
    • Flutter 骨架 - 一个包含许多这些建议的 Flutter 应用程序模板。
    • very_good_cli - Flutter 专家 Very Good Ventures 制作的 Flutter 应用程序模板。此模板生成类似的应用程序结构。
  • 文档
  • 工具
    • Flutter 开发者工具 - DevTools 是一套用于 Dart 和 Flutter 的性能和调试工具。
    • flutter_lints - 一个包含 Flutter 团队推荐的 Flutter 应用 lint 的包。使用此包可以鼓励团队之间良好的编码实践。

反馈

#

由于本网站的此部分正在不断发展,我们 欢迎您的反馈