Flutter GoRouter 路由导航详解

文章总体概览信息图

一、GoRouter 概述

GoRouter 是 Flutter 官方推荐的路由管理库,提供声明式路由配置和类型安全的导航。

1.1 安装依赖

dependencies:
  go_router: ^12.0.0

二、基本配置

2.1 创建路由配置

import 'package:go_router/go_router.dart';

final GoRouter router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomePage();
      },
    ),
    GoRoute(
      path: '/details/:id',
      builder: (BuildContext context, GoRouterState state) {
        return DetailPage(id: state.pathParameters['id']!);
      },
    ),
  ],
);

2.2 配置 MaterialApp

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
      title: 'GoRouter Demo',
    );
  }
}

三、路由导航

3.1 基本导航

// 导航到指定路径
context.push('/details/123');

// 导航并替换当前页面
context.pushReplacement('/details/123');

// 返回上一页
context.pop();

// 返回到根页面
context.popUntil((route) => route.isFirst);

3.2 带参数导航

// 路径参数
context.push('/user/${user.id}');

// 查询参数
context.push('/search?q=flutter');

// 额外参数
context.push('/details', extra: {'data': myData});

四、路由守卫

4.1 全局守卫

final GoRouter router = GoRouter(
  routes: [...],
  redirect: (BuildContext context, GoRouterState state) {
    final bool isLoggedIn = // 检查登录状态
    if (!isLoggedIn && state.location != '/login') {
      return '/login';
    }
    return null;
  },
);

4.2 路由级别守卫

GoRoute(
  path: '/profile',
  builder: (context, state) => const ProfilePage(),
  redirect: (context, state) {
    final bool isLoggedIn = // 检查登录状态
    return isLoggedIn ? null : '/login';
  },
);

五、嵌套路由

5.1 配置嵌套路由

GoRoute(
  path: '/dashboard',
  builder: (context, state) => const DashboardPage(),
  routes: [
    GoRoute(
      path: 'settings',
      builder: (context, state) => const SettingsPage(),
    ),
    GoRoute(
      path: 'profile',
      builder: (context, state) => const ProfilePage(),
    ),
  ],
);

5.2 使用 ShellRoute

final GoRouter router = GoRouter(
  routes: [
    ShellRoute(
      builder: (context, state, child) {
        return Scaffold(
          body: child,
          bottomNavigationBar: BottomNavigationBar(
            items: const [
              BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
              BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
            ],
          ),
        );
      },
      routes: [
        GoRoute(
          path: '/',
          builder: (context, state) => const HomePage(),
        ),
        GoRoute(
          path: '/settings',
          builder: (context, state) => const SettingsPage(),
        ),
      ],
    ),
  ],
);

六、类型安全路由

6.1 使用 TypedGoRoute

@TypedGoRoute<HomeRoute>(path: '/')
class HomeRoute extends GoRouteData {
  const HomeRoute();

  @override
  Widget build(BuildContext context, GoRouterState state) {
    return const HomePage();
  }
}

@TypedGoRoute<DetailRoute>(path: '/details/:id')
class DetailRoute extends GoRouteData {
  const DetailRoute({required this.id});

  final String id;

  @override
  Widget build(BuildContext context, GoRouterState state) {
    return DetailPage(id: id);
  }
}

6.2 类型安全导航

// 使用类型安全导航
HomeRoute().go(context);
DetailRoute(id: '123').push(context);

七、实战案例

7.1 完整路由配置

final GoRouter router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      name: 'home',
      builder: (context, state) => const HomePage(),
    ),
    GoRoute(
      path: '/login',
      name: 'login',
      builder: (context, state) => const LoginPage(),
    ),
    GoRoute(
      path: '/dashboard',
      name: 'dashboard',
      builder: (context, state) => const DashboardPage(),
      redirect: (context, state) {
        final authState = Provider.of<AuthState>(context, listen: false);
        return authState.isLoggedIn ? null : '/login';
      },
      routes: [
        GoRoute(
          path: 'profile',
          name: 'profile',
          builder: (context, state) => const ProfilePage(),
        ),
        GoRoute(
          path: 'settings',
          name: 'settings',
          builder: (context, state) => const SettingsPage(),
        ),
      ],
    ),
  ],
  errorBuilder: (context, state) => const ErrorPage(),
);

7.2 使用路由信息

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

  @override
  Widget build(BuildContext context) {
    final GoRouterState state = GoRouterState.of(context);
    final String id = state.pathParameters['id']!;
    final String? query = state.uri.queryParameters['q'];

    return Scaffold(
      appBar: AppBar(title: const Text('详情')),
      body: Center(
        child: Column(
          children: [
            Text('ID: $id'),
            if (query != null) Text('查询: $query'),
          ],
        ),
      ),
    );
  }
}

八、总结

GoRouter 提供了强大的路由管理功能:

  1. 声明式配置 - 集中配置所有路由
  2. 类型安全 - TypedGoRoute 确保类型安全
  3. 路由守卫 - 全局和路由级别守卫
  4. 嵌套路由 - 支持复杂的页面结构
  5. ShellRoute - 共享布局的路由

合理使用可以构建清晰的导航结构。

更多推荐