You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中使用GoRouter实现首次安装用户重定向至着陆页

实现GoRouter结合Riverpod认证状态重定向的最优方案

核心思路

把GoRouter的静态定义改成通过Riverpod Provider创建,这样就能在GoRouter内部访问WidgetRef,监听认证状态变化,实现动态重定向逻辑。

步骤1:重构GoRouter为Riverpod Provider

替换原来的静态goRouter变量,用Provider提供GoRouter实例,从而在内部获取ref并监听认证状态:

final goRouterProvider = Provider<GoRouter>((ref) {
  // 监听认证状态,状态更新时GoRouter会自动重建
  final userAsync = ref.watch(userAuthProvider);

  return GoRouter(
    initialLocation: '/',
    navigatorKey: _rootNavigatorKey,
    debugLogDiagnostics: true,
    // 重定向逻辑实现
    redirect: (context, state) {
      return userAsync.when(
        data: (userData) {
          final isAuthenticated = userData != null;
          final isOnWelcomePage = state.location == '/welcome';

          // 未登录且不在着陆页,跳转到/welcome
          if (!isAuthenticated && !isOnWelcomePage) {
            return '/welcome';
          }
          // 已登录但在着陆页,跳转到首页
          if (isAuthenticated && isOnWelcomePage) {
            return '/';
          }
          // 无需重定向
          return null;
        },
        loading: () => null, // 加载状态下不重定向,后续单独处理UI
        error: (error, stackTrace) => null, // 错误状态可根据需求跳转到错误页
      );
    },
    routes: [
      // 添加着陆页路由
      GoRoute(
        path: '/welcome',
        builder: (context, state) => const WelcomePage(),
      ),
      // 原有的嵌套路由结构
      StatefulShellRoute.indexedStack(
        builder: (context, state, navigationShell) {
          return ScaffoldWithNestedNavigation(navigationShell: navigationShell);
        },
        branches: [
          StatefulShellBranch(
            navigatorKey: _shellNavigatorHomeKey,
            routes: [
              GoRoute(
                path: '/',
                builder: (BuildContext context, GoRouterState state) =>
                    const MyHomePage(),
                routes: [
                  GoRoute(
                    path: 'settimer',
                    parentNavigatorKey: _rootNavigatorKey,
                    builder: (context, state) => const SetTimer(),
                  ),
                  GoRoute(
                    path: 'countdown',
                    parentNavigatorKey: _rootNavigatorKey,
                    builder: (context, state) => const CountDownPage(),
                  ),
                ],
              ),
            ],
          ),
          StatefulShellBranch(
            navigatorKey: _shellNavigatorStatsKey,
            routes: [
              GoRoute(
                path: '/statspage',
                builder: (BuildContext context, GoRouterState state) =>
                    const StatsPage(),
              ),
            ],
          ),
          StatefulShellBranch(
            navigatorKey: _shellNavigatorMoreKey,
            routes: [
              GoRoute(
                path: '/morepage',
                builder: (BuildContext context, GoRouterState state) =>
                    const MorePage(),
              ),
            ],
          ),
        ],
      ),
    ],
    // 处理加载、错误状态的UI
    errorBuilder: (context, state) {
      return userAsync.when(
        data: (_) => const ErrorWidget('未知错误'),
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (error, stackTrace) => ErrorWidget('认证错误: $error'),
      );
    },
  );
});

// 保留原导航键定义
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorHomeKey = GlobalKey<NavigatorState>();
final _shellNavigatorStatsKey = GlobalKey<NavigatorState>();
final _shellNavigatorMoreKey = GlobalKey<NavigatorState>();

步骤2:修改MyApp使用Provider提供的GoRouter

在MyApp的build方法中,通过ref.watch获取GoRouter实例,传递给MaterialApp.router:

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final goRouter = ref.watch(goRouterProvider);
    final activetheme = ref.watch(thememodeProvider);

    return MaterialApp.router(
      title: 'Flutter Demo',
      routerConfig: goRouter,
      debugShowCheckedModeBanner: false,
      themeMode: activetheme,
      theme: MyThemes.lightTheme,
      darkTheme: MyThemes.darkTheme,
    );
  }
}

关键细节说明

  1. 状态联动:通过ref.watch(userAuthProvider)监听认证状态,状态变化时GoRouter自动重建,保证重定向逻辑始终基于最新用户状态。
  2. 避免循环重定向:判断当前路径是否为目标页,防止已登录用户反复跳转到首页、未登录用户反复跳转到着陆页的问题。
  3. 状态反馈:在errorBuilder中处理加载和错误状态,给用户提供明确的UI反馈,避免空白页面。
  4. 路由完整性:新增/welcome路由,确保重定向目标存在,避免路由未定义错误。

内容的提问来源于stack exchange,提问作者Milan Labus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:34:54