如何结合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
相关产品推荐
相关产品推荐

