Flutter增强路由管理插件go_router_plus的使用

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

Flutter增强路由管理插件 go_router_plus 的使用

Go Router Plus 是一个增强版的路由管理插件,基于 go_router,旨在解决大型应用中复杂的路由管理和重定向逻辑。本文将详细介绍如何使用 go_router_plus 来构建和管理路由。

安装

首先,通过以下命令安装 go_router_plus

flutter pub add go_router_plus

安装完成后,可以在 Dart 文件中导入该包:

import 'package:go_router_plus/go_router_plus.dart';

创建屏幕(Screens)

go_router_plus 中,每个屏幕都需要继承自 Screen 类,并实现一些必要的方法和属性。

示例:创建第一个屏幕

// lib/screens/my_first_screen.dart

import 'package:go_router_plus/go_router_plus.dart';
import 'package:flutter/material.dart';

class MyFirstScreen extends Screen {
  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return const Text('Hello world');
  }

  [@override](/user/override)
  String get routeName => 'my_first_screen';

  [@override](/user/override)
  String get routePath => '/my-first-screen';
}

必须实现的方法和属性:

  • build(BuildContext context, GoRouterState state):返回 WidgetPage<void>,通常情况下返回 Widget
  • routeName:唯一标识该屏幕的名称。
  • routePath:该屏幕对应的路径。

标记初始屏幕

如果要设置初始屏幕,可以通过实现 InitialScreen 接口来标记某个屏幕为初始屏幕:

class LoginScreen extends Screen implements InitialScreen {
  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return const Text('Login screen');
  }

  [@override](/user/override)
  String get routeName => 'login';

  [@override](/user/override)
  String get routePath => '/login';
}

标记错误屏幕

当遇到路由错误时,可以使用 ErrorScreen 接口来定义一个错误页面:

class MyErrorScreen extends Screen implements ErrorScreen {
  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return Text(state.error.toString());
  }

  [@override](/user/override)
  String get routeName => 'error';

  [@override](/user/override)
  String get routePath => '/error';
}

嵌套路由(Nested Navigation)

ShellRoute 提供了嵌套路由的支持,允许你将多个子路由包裹在一个 UI Shell 中。你可以通过继承 ShellScreen 来实现嵌套路由:

class MyShellScreen extends ShellScreen {
  [@override](/user/override)
  List<ScreenBase> subScreens() {
    return [
      ScreenA(),
      ScreenB(),
    ];
  }
}

创建路由

使用 createGoRouter 工厂函数来创建路由配置:

final router = createGoRouter(
  screens: [
    LoginScreen(),
    MyFirstScreen(),
    MyErrorScreen(),
  ],
);

重定向器(Redirectors)

Redirector 负责处理所有路由的重定向逻辑。你可以通过 redirectors 参数传递多个重定向器。

认证重定向

AuthRedirector 提供了一个内置的认证重定向功能,帮助你根据用户登录状态进行重定向。

示例:实现认证重定向

class AuthService with ChangeNotifier implements LoggedInState {
  bool _loggedIn = false;

  [@override](/user/override)
  bool get loggedIn => _loggedIn;

  void login() {
    _loggedIn = true;
    notifyListeners();
  }

  void logout() {
    _loggedIn = false;
    notifyListeners();
  }
}

class LoginScreen extends Screen implements GuestScreen {
  [@override](/user/override)
  String get routePath => '/login';

  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return Scaffold(
      body: const Text('Login screen'),
      floatingActionButton: FloatingActionButton(
        onPressed: () => AuthService().login(),
        child: const Icon(Icons.login),
      ),
    );
  }
}

class HomeScreen extends Screen implements UserScreen {
  [@override](/user/override)
  String get routePath => '/home';

  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return Scaffold(
      body: const Text('Home screen'),
      floatingActionButton: FloatingActionButton(
        onPressed: () => AuthService().logout(),
        child: const Icon(Icons.logout),
      ),
    );
  }
}

final authService = AuthService();

final router = createGoRouter(
  screens: [
    LoginScreen(),
    HomeScreen(),
  ],
  redirectors: [
    AuthRedirector(
      state: authService,
      guestRedirectPath: '/login',
      userRedirectPath: '/home',
    ),
  ],
);

屏幕重定向

如果你需要为某些屏幕实现自定义的重定向逻辑,可以实现 RedirectAware 接口:

class VipScreen extends Screen implements UserScreen, RedirectAware {
  [@override](/user/override)
  FutureOr<String?> redirect(BuildContext context, GoRouterState state) {
    // 检查当前用户是否是 VIP
    final currentUser = ...; // 获取当前用户信息
    return !currentUser.isVip ? '/home' : null;
  }

  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return const Text('VIP Screen');
  }

  [@override](/user/override)
  String get routePath => '/vip';
}

然后在创建路由时添加 ScreenRedirector

final router = createGoRouter(
  screens: [
    LoginScreen(),
    HomeScreen(),
    VipScreen(),
  ],
  redirectors: [
    ScreenRedirector(),
    AuthRedirector(
      state: authService,
      guestRedirectPath: '/login',
      userRedirectPath: '/home',
    ),
  ],
);

刷新监听器(Refresh Notifiers)

go_router_plus 允许你添加多个刷新监听器,以便在某些状态变化时重新触发重定向逻辑。

示例:添加刷新监听器

class PromotionService with ChangeNotifier {
  void activate() {
    notifyListeners();
  }
}

final authService = AuthService();
final promotionService = PromotionService();

final router = createGoRouter(
  screens: [
    ManageUserScreen(),
  ],
  redirectors: [
    AuthRedirector(
      state: authService,
      guestRedirectPath: '/login',
      userRedirectPath: '/home',
    ),
  ],
  refreshNotifiers: [
    authService,
    promotionService,
  ],
);

完整示例 Demo

以下是一个完整的示例代码,展示了如何使用 go_router_plus 构建一个简单的登录和主页应用:

import 'package:flutter/material.dart';
import 'package:go_router_plus/go_router_plus.dart';

void main() {
  final authService = AuthService();
  final router = createGoRouter(
    screens: [
      LoginScreen(authService),
      HomeScreen(authService),
    ],
    redirectors: [
      AuthRedirector(
        state: authService,
        guestRedirectPath: '/login',
        userRedirectPath: '/home',
      ),
    ],
    refreshNotifiers: [
      authService,
    ],
  );

  runApp(
    MaterialApp.router(
      routeInformationParser: router.routeInformationParser,
      routerDelegate: router.routerDelegate,
      routeInformationProvider: router.routeInformationProvider,
    ),
  );
}

class LoginScreen extends Screen implements InitialScreen, GuestScreen {
  LoginScreen(this.authService);

  final AuthService authService;

  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return Scaffold(
      body: const Center(child: Text('Login screen')),
      floatingActionButton: FloatingActionButton(
        onPressed: authService.login,
        child: const Icon(Icons.login),
      ),
    );
  }

  [@override](/user/override)
  String get routeName => 'login';

  [@override](/user/override)
  String get routePath => '/login';
}

class HomeScreen extends Screen implements UserScreen {
  HomeScreen(this.authService);

  final AuthService authService;

  [@override](/user/override)
  Widget build(BuildContext context, GoRouterState state) {
    return Scaffold(
      body: const Center(child: Text('Home screen')),
      floatingActionButton: FloatingActionButton(
        onPressed: authService.logout,
        child: const Icon(Icons.logout),
      ),
    );
  }

  [@override](/user/override)
  String get routeName => 'home';

  [@override](/user/override)
  String get routePath => '/home';
}

class AuthService with ChangeNotifier implements LoggedInState {
  bool _loggedIn = false;

  [@override](/user/override)
  bool get loggedIn => _loggedIn;

  void login() {
    _loggedIn = true;
    notifyListeners();
  }

  void logout() {
    _loggedIn = false;
    notifyListeners();
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用go_router_plus插件来增强路由管理的代码示例。go_router_plus是一个扩展自go_router的插件,提供了更多高级功能,比如嵌套导航、全局守卫等。

首先,确保你已经在pubspec.yaml文件中添加了go_router_plus依赖:

dependencies:
  flutter:
    sdk: flutter
  go_router: ^5.0.0 # 请注意版本号,确保与go_router_plus兼容
  go_router_plus: ^x.y.z # 替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来是一个简单的示例,展示如何使用go_router_plus进行路由管理:

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

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

class MyApp extends StatelessWidget {
  final GoRouterPlus _goRouterPlus = GoRouterPlus(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => HomeScreen(),
        routes: [
          GoRoute(
            path: 'details/:id',
            builder: (context, state) {
              final id = state.params['id']!;
              return DetailsScreen(id: id);
            },
          ),
        ],
      ),
    ],
    navigatorBuilders: <Type, NavigatorBuilder>{
      MaterialNavigator: (navigatorKey, router, builder) {
        return MaterialApp.router(
          key: navigatorKey,
          router: router,
          builder: builder,
          title: 'GoRouterPlus Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
        );
      },
    },
    errorPageBuilder: (context, state) {
      // 自定义错误页面
      return Scaffold(
        appBar: AppBar(title: Text('Error')),
        body: Center(
          child: Text('An error occurred: ${state.error.toString()}'),
        ),
      );
    },
    redirectingPageBuilder: (context, state) {
      // 自定义重定向页面(可选)
      return Scaffold(
        appBar: AppBar(title: Text('Redirecting')),
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    },
  );

  @override
  Widget build(BuildContext context) {
    return _goRouterPlus.router.builder(context);
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 导航到详情页面,传递参数
            context.go('/details/123');
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsScreen extends StatelessWidget {
  final String id;

  DetailsScreen({required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details')),
      body: Center(
        child: Text('Details for ID: $id'),
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 定义路由:使用GoRouterPlus定义了一个路由表,其中包含一个根路由/和一个嵌套路由/details/:id
  2. 导航器构建器:使用navigatorBuilders定义了MaterialNavigator的构建方式,这样可以自定义MaterialApp的主题和其他属性。
  3. 错误页面:使用errorPageBuilder自定义了一个错误页面,当路由发生错误时会显示这个页面。
  4. 重定向页面(可选):使用redirectingPageBuilder自定义了一个重定向页面,当路由正在进行重定向时会显示这个页面(本例中未实际触发重定向,仅作为示例)。
  5. 导航:在HomeScreen中使用context.go方法导航到详情页面,并传递了一个参数id

这个示例展示了如何使用go_router_plus进行基本的路由管理和错误处理。根据具体需求,你可以进一步扩展这个示例,比如添加全局守卫、嵌套导航等高级功能。

回到顶部