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

如何结合Firebase Auth状态变化使用GoRouter实现页面重定向

如何让GoRouter监听Firebase Auth状态变化并实现自动重定向?

问题描述

此前仅通过StreamBuilder监听Firebase Auth状态,使用initialRoute管理页面路由。现在希望借助GoRouter,在Firebase Auth用户不为空时自动重定向页面,但不清楚如何让GoRouter监听Auth状态变化。相关代码如下:

Main.dart类

Widget build(BuildContext context) {
    return StreamBuilder<User?>(
        stream: authservice.authState,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            print(snapshot.data);
            return Sizer(builder: ((context, orientation, deviceType) {
              return MaterialApp.router(
                builder: (context, child) => ResponsiveWrapper.builder(child,
                    maxWidth: 1200,
                    minWidth: 480,
                    defaultScale: true,
                    breakpoints: [
                      const ResponsiveBreakpoint.resize(450, name: MOBILE),
                      const ResponsiveBreakpoint.autoScale(800, name: TABLET),
                      const ResponsiveBreakpoint.autoScale(1000, name: TABLET),
                      const ResponsiveBreakpoint.resize(1200, name: DESKTOP),
                      const ResponsiveBreakpoint.autoScale(2460, name: "4K"),
                    ],
                    background: Container(color: const Color(0xFFF5F5F5))),
                title: 'Welcome',
                theme: ThemeData(primaryColor: Colors.blueGrey),
                // initialRoute: snapshot.data != null ? "/dashboard" : "/intro",
                // routes: {
                //   '/': (context) => const Intro(),
                //   '/dashboard': (context) => const Dashboard(),
                //   '/login': (context) => const Login(),
                //   '/register': (context) => const Register()
                // },
                routerConfig: router,
              );
            }));
          }
          return const Loading();
        });
  }

GoRouter类

final GoRouter router = GoRouter(
    routes: routes,
    initialLocation: '/login',
    debugLogDiagnostics: true,
    routerNeglect: true);

List<RouteBase> routes = [
  GoRoute(
    path: '/login',
    name: 'login',
    builder: (context, state) => const Login(),
  ),
  GoRoute(
    path: '/register',
    name: 'register',
    builder: (context, state) => const Register(),
  ),
  GoRoute(
    path: '/intro',
    name: 'intro',
    builder: (context, state) => const Intro(),
  ),
  GoRoute(
    path: '/dashboard',
    name: 'dashboard',
    builder: (context, state) => const Dashboard(),
  ),
];

AuthService类

final FirebaseAuth _auth = FirebaseAuth.instance;

  Stream<User?> get authState => _auth.authStateChanges();

解决方案

核心思路是利用GoRouter的refreshListenable参数监听Auth状态变化,结合redirect方法实现自动路由跳转,无需在外层嵌套StreamBuilder。具体步骤如下:

1. 改造AuthService,添加状态通知能力

让AuthService继承ChangeNotifier,监听Firebase Auth状态变化,当用户状态更新时通知GoRouter刷新路由逻辑:

class AuthService extends ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  User? _currentUser;

  AuthService() {
    // 监听Firebase Auth状态变化,更新本地用户并通知监听者
    _auth.authStateChanges().listen((User? user) {
      _currentUser = user;
      notifyListeners();
    });
  }

  // 获取当前用户
  User? get currentUser => _currentUser;
  // 保留原有Stream供其他场景使用
  Stream<User?> get authState => _auth.authStateChanges();
}

2. 配置GoRouter,实现状态监听与重定向

在GoRouter初始化时,通过refreshListenable绑定AuthService,同时在redirect方法中根据用户状态和当前路由决定是否重定向:

final AuthService authService = AuthService();

final GoRouter router = GoRouter(
  routes: routes,
  initialLocation: '/intro',
  debugLogDiagnostics: true,
  // 绑定AuthService,状态变化时自动刷新路由逻辑
  refreshListenable: authService,
  redirect: (context, state) {
    final isLoggedIn = authService.currentUser != null;
    final currentLocation = state.location;

    // 已登录状态:如果当前在登录/注册/引导页,重定向到仪表盘
    if (isLoggedIn) {
      if (currentLocation == '/login' || currentLocation == '/register' || currentLocation == '/intro') {
        return '/dashboard';
      }
    } 
    // 未登录状态:如果当前不在登录/注册/引导页,重定向到引导页
    else {
      if (!['/login', '/register', '/intro'].contains(currentLocation)) {
        return '/intro';
      }
    }

    // 无需重定向时返回null
    return null;
  },
);

List<RouteBase> routes = [
  GoRoute(
    path: '/intro',
    name: 'intro',
    builder: (context, state) => const Intro(),
  ),
  GoRoute(
    path: '/login',
    name: 'login',
    builder: (context, state) => const Login(),
  ),
  GoRoute(
    path: '/register',
    name: 'register',
    builder: (context, state) => const Register(),
  ),
  GoRoute(
    path: '/dashboard',
    name: 'dashboard',
    builder: (context, state) => const Dashboard(),
  ),
];

3. 简化Main.dart,移除外层StreamBuilder

GoRouter已接管Auth状态监听和路由逻辑,无需再用StreamBuilder包裹,直接返回MaterialApp.router即可:

Widget build(BuildContext context) {
  return Sizer(builder: ((context, orientation, deviceType) {
    return MaterialApp.router(
      builder: (context, child) => ResponsiveWrapper.builder(child,
          maxWidth: 1200,
          minWidth: 480,
          defaultScale: true,
          breakpoints: [
            const ResponsiveBreakpoint.resize(450, name: MOBILE),
            const ResponsiveBreakpoint.autoScale(800, name: TABLET),
            const ResponsiveBreakpoint.autoScale(1000, name: TABLET),
            const ResponsiveBreakpoint.resize(1200, name: DESKTOP),
            const ResponsiveBreakpoint.autoScale(2460, name: "4K"),
          ],
          background: Container(color: const Color(0xFFF5F5F5))),
      title: 'Welcome',
      theme: ThemeData(primaryColor: Colors.blueGrey),
      routerConfig: router,
    );
  }));
}

逻辑说明

  • 当用户登录/登出时,AuthService会触发notifyListeners(),GoRouter收到通知后重新执行redirect方法,自动调整路由。
  • redirect方法中可以根据业务需求自定义重定向规则,比如未登录用户访问仪表盘时跳转到登录页,已登录用户访问登录页时跳转到仪表盘。

内容的提问来源于stack exchange,提问作者Muzamil Haq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:17:56