Flutter模块化路由管理插件go_router_modular的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter模块化路由管理插件go_router_modular的使用

GoRouter Modular 简介 🧩 💉

GoRouter Modular 通过实现模块化架构简化了Flutter开发。它利用 GoRouter 进行路由管理,并支持每个模块的依赖注入与自动释放。

通过 GoRouter Modular,你可以轻松地将应用程序组织成独立的模块,简化代码开发和维护,同时促进组件复用和项目可扩展性。使用 GoRouter Modular 简化你的 Flutter 应用程序开发并加速工作流程。

安装 Installation

在终端中执行以下命令来添加 go_router_modular:

flutter pub add go_router_modular

或者,在 pubspec.yaml 文件中添加如下依赖项:

dependencies:
  go_router_modular: ^2.0.1+2

开始 Start

为了开始使用 GoRouter Modular,你需要完成以下几个步骤:

  1. 创建 app_module.dart
  2. 创建 app_widget.dart
  3. 配置 main.dart

项目结构示例 Project Structure example

📁 src
   📁 modules
      📁 home
         📄 home_controller.dart
         📄 home_page.dart
         📄 home_module.dart
   📄 app_module.dart
   📄 app_widget.dart
📄 main.dart

Main Example

import 'package:example/src/app_module.dart';
import 'package:example/src/app_widget.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';
import 'package:flutter_web_plugins/url_strategy.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  if (kIsWeb) usePathUrlStrategy();

  Modular.configure(appModule: AppModule(), initialRoute: "/"); // Configure Modular

  runApp(AppWidget()); // Define AppWidget
}

AppWidget Example

import 'package:example/src/app_module.dart';
import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';

class AppWidget extends StatelessWidget {
  const AppWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: Modular.routerConfig, // Define Router config
      title: 'Modular GoRoute Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}

AppModule Example

import 'package:example/src/modules/home/home_module.dart';
import 'package:example/src/modules/user/aplication/user_store.dart';
import 'package:example/src/modules/user/user_module.dart';
import 'package:go_router_modular/go_router_modular.dart';

class AppModule extends Module {
  @override
  List<Bind<Object>> get binds => [
        Bind.singleton<AuthController>((i) => AuthController()), // define binds global in app_module
      ];

  @override
  List<ModularRoute> get routes => [ // define modules
        ModuleRoute("/", module: HomeModule()),
      ];
}

依赖注入 DEPENDECY INJECTION 💉

⚠️ 注意:每个依赖项当放置在 BIND 中时必须是有类型的,以确保正确操作。

Injecting a Dependency

你应当为你的模块创建一个类并继承自 Module,然后在 binds 中添加你的依赖项。

每当没有指向你的模块的路由时,模块将自动处理掉这些绑定。

import 'package:example/src/modules/home/presenters/home_page.dart';
import 'package:go_router_modular/go_router_modular.dart';

class HomeModule extends Module {
  @override
  List<Bind<Object>> get binds => [
         Bind.singleton<HomeController>((i) => HomeController()), // DEFINE BINDS FOR MODULE
         Bind.factory<IUserRepository>((i) => UserRepository()),
      ];
}

Injecting a Dependency Globally

只需将你的 binds 放置在 AppModule 中即可。

AppModule 永远不会被释放。

class AppModule extends Module {
  @override
  List<Bind<Object>> get binds => [
        Bind.singleton<AuthController>((i) => AuthController()), // DEFINE GLOBAL BINDS IN APP_MODULE
      ];
}

Retrieve a Bind

要检索一个绑定,我们有三种选择:

final homeController = context.read<HomeController>();
// 或者
final homeController = Modular.get<HomeController>();
// 或者
final homeController = Bind.get<HomeController>();

路由 Routes 🛣️

路由控制由我们的 go_router 完成。唯一的变化是我们将路由配置留给模块使用 ChildRoute,其结构与 GoRoute 相同。有关导航,请参阅 go_router 文档。

ChildRoute() 相当于 GoRoute()。您可能会注意到它们具有相同的参数。

注意,每个模块的初始路由必须以 “/” 开头。

ChildRoutes 示例

class HomeModule extends Module {

  @override
    List<ModularRoute> get routes => [
        ChildRoute('/', name: "home", builder: (context, state) => const HomePage()), // define routes
        ChildRoute('/config', name: "config", builder: (context, state) => const ConfigPage()),
        ChildRoute('/info_product/:id', name: "info_product", builder: (context, state) => const InfoProductPage(id: state.pathParameters['id']!)),
      ];
}

ShellRoutes 示例

ShellModularRoute 类似于 FLutter Modular 的 RouteOutlet,可用于在页面内构建导航窗口。常用于菜单构造,其中只更改屏幕内容。

class HomeShellModule extends Module {

  @override
  List<ModularRoute> get routes => [
        ShellModularRoute(builder: (context, state, child) => ShellPageExample(shellChild: child),  routes:[
          ChildRoute("/config", child: (context, state) => const ConfigPage()),
          ChildRoute("/user", child: (context, state) => const UserPage()),
          ChildRoute("/orders", child: (context, state) => const OrdersPage()),
        ],
      ),
      ];
}

ShellPageExample 示例

class ShellPageExample extends StatefulWidget {
  final Widget shellChild; // 请求子WIDGET以渲染在shell中
  const ShellPageExample({super.key, required this.shellChild});

  @override
  State<ShellPageExample> createState() => _ShellPageExampleState();
}

class _ShellPageExampleState extends State<ShellPageExample> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(children: [
        Expanded(child: widget.shellChild), // 子路由将在此重新渲染
        Row(
          children: [
            IconButton(
                onPressed: () {
                  context.go("/home");
                },
                icon: const Icon(Icons.home)),
            IconButton(
                onPressed: () {
                  context.go("/config");
                },
                icon: const Icon(Icons.settings)),
          ],
        ),
      ]),
    );
  }
}

Go 直接到目的地示例

在 GoRouter 中导航到目的地会替换当前的屏幕栈。要切换到新屏幕,可以调用 context.go() 并传入 URL:

build(BuildContext context) {
  return TextButton(
    onPressed: () => context.go('/users/123'),
  );
}

要构建带有查询参数的 URI,可以使用 Dart 标准库中的 Uri 类:

context.go(Uri(path: '/users/123', queryParameters: {'filter': 'abc'}).toString());

更多信息

示例代码

import 'package:example/src/app_module.dart';
import 'package:example/src/app_widget.dart';
import 'package:example/src/core/routes.dart';
import 'package:flutter/material.dart';

import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:go_router_modular/go_router_modular.dart';

void main() {
  setUrlStrategy(PathUrlStrategy());

  Modular.configure(
    appModule: AppModule(),
    initialRoute: Routes.slpash.route,
    debugLogDiagnosticsGoRouter: true,
  );
  runApp(const AppWidget());
}

更多关于Flutter模块化路由管理插件go_router_modular的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter模块化路由管理插件go_router_modular的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用go_router_modular插件进行模块化路由管理的代码案例。go_router_modular结合了go_router和模块化概念,使得路由管理更加清晰和模块化。

1. 添加依赖

首先,在pubspec.yaml文件中添加go_routergo_router_modular的依赖:

dependencies:
  flutter:
    sdk: flutter
  go_router: ^4.0.0 # 请检查最新版本
  go_router_modular: ^3.0.0 # 请检查最新版本

然后运行flutter pub get来获取依赖。

2. 创建模块

假设我们有两个模块:home_modulesettings_module

home_module/home_module.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_modular/go_router_modular.dart';

class HomeModule extends Module {
  @override
  List<RouteDefinition> get routes => [
    RouteDefinition(
      path: '/',
      name: 'home',
      builder: (_, __) => HomeScreen(),
    ),
  ];
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.go('/settings'),
          child: Text('Go to Settings'),
        ),
      ),
    );
  }
}

settings_module/settings_module.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_modular/go_router_modular.dart';

class SettingsModule extends Module {
  @override
  List<RouteDefinition> get routes => [
    RouteDefinition(
      path: '/settings',
      name: 'settings',
      builder: (_, __) => SettingsScreen(),
    ),
  ];
}

class SettingsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Settings')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.go('/'),
          child: Text('Go to Home'),
        ),
      ),
    );
  }
}

3. 配置主应用

在主应用文件中配置GoRouter和模块化路由。

main.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_modular/go_router_modular.dart';
import 'home_module/home_module.dart';
import 'settings_module/settings_module.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final GoRouter _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        redirect: (context, state) => '/home',
      ),
      ...HomeModule().routes,
      ...SettingsModule().routes,
    ],
    errorPageBuilder: (context, state) {
      return Scaffold(
        appBar: AppBar(title: Text('Error')),
        body: Center(child: Text('404 Not Found')),
      );
    },
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      router: _router,
      routeInformationParser: _router.routeInformationParser,
    );
  }
}

4. 运行应用

现在,你可以运行你的Flutter应用。点击Home屏幕上的按钮将导航到Settings屏幕,点击Settings屏幕上的按钮将导航回Home屏幕。

这个代码案例展示了如何使用go_router_modular进行模块化路由管理。通过定义不同的模块,并将每个模块的路由配置添加到主应用的GoRouter中,你可以实现清晰且可维护的路由结构。

回到顶部