flutter_modular
具有依赖注入和路由管理的智能项目结构
一个智能的项目结构
具有依赖注入和路由管理的智能项目结构
用于 flutter_modular 的代码生成。注入自动化。注解 @Inject、@Param 和 @Data。
具有依赖注入和路由管理的智能项目结构
具有依赖注入和路由管理的智能项目结构
>=2.2.0 <3.0.0>=1.3.0 <2.0.0>=0.5.0 <2.0.0{"sdk":"flutter"}{"sdk":"flutter"}^0.0.2{"sdk":"flutter"}以下为英文项目原文快照,最新内容请访问 GitHub。
A smart, modular project structure
Route management, dependency injection and scoped state — organized by feature, the Flutter way.
flutter_modular v7 pub version license
Documentation · Report Bug · Request Feature
Maintained by Flutterando
Let's find out how to implement a Modular structure in your project.
Modular proposes to solve two problems:
In a monolithic architecture, where we have our entire application as a single module, we design our software in a quick and elegant way, taking advantage of all the amazing features of Flutter💙. However, producing a larger app in a "monolithic" way can generate technical debt in both maintanance and scalability. With this in mind, developers adopted architectural strategies to better divide the code, minimizing the negative impacts on the project's maintainability and scalability..
By better dividing the scope of features, we gain:
With a more readable code, we extend the life of the project. See example of a standard MVC with 3 features(Auth, Home, Product):
.
├── models # All models
│ ├── auth_model.dart
│ ├── home_model.dart
│ └── product_model.dart
├── controller # All controllers
│ ├── auth_controller.dart
│ ├── home_controller.dart
│ └── product_controller.dart
├── views # All views
│ ├── auth_page.dart
│ ├── home_page.dart
│ └── product_page.dart
├── core # Tools and utilities
├── app_widget.dart # Main Widget containing MaterialApp
└── main.dart # runApp
Here we have a default structure using MVC. This is incredibly useful in almost every application.
Let's see how the structure looks when we divide by scope:
.
├── features # All features or Modules
│ ├─ auth # Auth's MVC
│ │ ├── auth_model.dart
│ │ ├── auth_controller.dart
│ │ └── auth_page.dart
│ ├─ home # Home's MVC
│ │ ├── home_model.dart
│ │ ├── home_controller.dart
│ │ └── home_page.dart
│ └─ product # Product's MVC
│ ├── product_model.dart
│ ├── product_controller.dart
│ └── product_page.dart
├── core # Tools and utilities
├── app_widget.dart # Main Widget containing MaterialApp
└── main.dart # runApp
What we did in this structure was to continue using MVC, but this time in scope. This means that each feature has its own MVC, and this simple approach solves many scalability and maintainability issues. We call this approach "Smart Structure". But two things were still Global and clashed with the structure itself, so we created Modular to solve this impasse.
In short: Modular is a solution to modularize the route and dependency injection system, making each scope have its own routes and injections independent of any other factor in the structure. We create objects to group the Routes and Injections and call them Modules.
Modular is not only ingenious for doing something amazing like componentizing Routes and Dependency Injections, it's amazing for being able to do all this simply!
Go to the next topic and start your journey towards an intelligent structure.
Does Modular work with any state management approach?
Can I use dynamic routes?
:params,
query strings, relative paths, nested routes and persistent shells (RouterOutlet).
Use a route guard to redirect (e.g. to a 404 or a login page).Do I need to create a Module for all features?
flutter_modular 7 is a ground-up rewrite. A Module is now exactly the two things that couple a Flutter app — Dependency Injection + Routes — declared with a small functional API. State is page-scoped, tied to the route lifecycle, so ownership and disposal stop being your problem and the durable truth lives in a repository/service registered in DI. Full, runnable demonstrations (nested routes,
RouterOutletshells, route guards, per-module DI lifecycle,arguments/pop-results) live inexample/.
dependencies:
flutter_modular: ^7.0.0
or run flutter pub add flutter_modular.
A module groups routes and dependency injection. Shared dependencies are registered with addSingleton/add*, routes with route(...), and submodules with module(...).
import 'package:flutter_modular/flutter_modular.dart';
final appModule = createModule(register: (c) {
c
..addSingleton<Counter>(Counter.new) // shared dependency (SSoT)
..route('/', child: (ctx, state) => const HomePage())
..route('/details/:id',
child: (ctx, state) => DetailsPage(id: state.params['id']!));
});
ModularApp is the first widget, above MaterialApp. It bootstraps the module, owns the injector, and exposes the router config.
void main() => runApp(
ModularApp(module: appModule, child: const AppRoot()),
);
class AppRoot extends StatelessWidget {
const AppRoot({super.key});
@override
Widget build(BuildContext context) => MaterialApp.router(
routerConfig: ModularApp.routerConfigOf(context),
);
}
context.pushNamed('/details/42'); // stacks a page (push stays out of the URL)
context.navigate('/'); // replaces the stack (owns the URL, resets history)
context.pop(result); // pops, delivering a result to the awaiting pushNamed
State lives 1:1 with a view via provide — built in a page-local scope and disposed when the route leaves, so there are no floating globals and no manual dispose.
c.route('/counter',
provide: (s) => s.addChangeNotifier<CounterViewModel>(CounterViewModel.new),
child: (ctx, state) => const CounterPage(),
);
// inside the page:
final vm = context.watch<CounterViewModel>(); // rebuilds when the VM notifies
// granular: rebuild only when the selected value changes (provider-style)
final count = context.select<CounterViewModel, int>((vm) => vm.count);
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the appropriate tag. Don't forget to give the project a star! Thanks again!
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Remember to include a tag, and to follow Conventional Commits and Semantic Versioning when uploading your commit and/or creating the issue.
Flutterando Community
This fork version is maintained by Flutterando.