GoRouter始终仅显示登录页,各类导航操作无效问题求助
问题:Flutter应用导航始终停留在登录页,重定向与authState监听未触发
我的应用无论执行何种导航操作(如设置初始路由至其他页面、context.push、context.go等),始终仅显示登录页面。我在认证系统中实现了重定向函数,未认证时会跳转回登录页,但这似乎不是问题根源——点击导航按钮时,两个打印语句"authState changes"和"Redirect!"均未触发。
提供的代码
main.dart
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:sneaker_app/models/cart.dart'; import 'package:sneaker_app/routes/app_route_config.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:sneaker_app/services/auth_service.dart'; import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); // Referesh GoRouter configuration every time authState changes (Authentication guaranteed) FirebaseAuth.instance.authStateChanges().listen((User? user) { print("authState changes"); MyAppRouter.router.refresh(); }); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider<Cart>(create: (context) => Cart()), ChangeNotifierProvider<AuthService>( create: (context) => AuthService()) ], child: MaterialApp.router( debugShowCheckedModeBanner: false, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.grey)), routerConfig: MyAppRouter.router, )); } }
路由配置文件(app_route_config.dart)
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:sneaker_app/models/shopee_tile.dart'; import 'package:sneaker_app/pages/home_page.dart'; import 'package:sneaker_app/pages/item_page.dart'; import 'package:sneaker_app/pages/login_page.dart'; import 'package:sneaker_app/pages/signup_page.dart'; import 'package:sneaker_app/routes/app_route_constants.dart'; import 'package:sneaker_app/services/auth_service.dart'; class MyAppRouter { static final GoRouter router = GoRouter( initialLocation: "/login", routes: [ GoRoute( name: MyAppRouteConstants.homeRouteName, path: "/", builder: (context, state) => HomePage()), GoRoute( name: MyAppRouteConstants.itemRouteName, path: "/item/:id", builder: (context, state) { ShopeeTile item = state.extra as ShopeeTile; return ItemPage( id: int.parse(state.pathParameters["id"]!), item: item, ); }), GoRoute( name: MyAppRouteConstants.loginRouteName, path: "/login", builder: (context, state) => LoginPage()), GoRoute( name: MyAppRouteConstants.signupRouteName, path: "/signup", builder: (context, state) => SignupPage()), ], redirect: (BuildContext context, GoRouterState state) async { final bool loggedIn = Provider.of<AuthService>(context, listen: false).user != null; final bool loggingIn = state.matchedLocation == "/login"; print("Redirect!"); if (!loggedIn) return "/login"; if (loggingIn) return "/"; // no need to redirect at all return null; }, ); }
登录页按钮代码
TextButton( child: Text('Sign up'), onPressed: () { context.pushNamed(MyAppRouteConstants.signupRouteName); }, ),
问题分析与解决方案
核心问题总结
- GoRouter的
redirect回调被错误标记为异步,导致逻辑执行异常 - 重定向逻辑未允许未登录用户访问注册页,强制跳转回登录页
- FirebaseAuth的状态变化未同步到AuthService,导致重定向逻辑一直判定为未登录
- GoRouter未监听AuthService的状态变化,无法自动触发重定向更新
修改后的代码
1. 更新AuthService(添加状态同步方法)
class AuthService extends ChangeNotifier { User? _user; User? get user => _user; // 用于同步FirebaseAuth的用户状态 void setUser(User? newUser) { _user = newUser; notifyListeners(); } }
2. 修改路由配置文件
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:sneaker_app/models/shopee_tile.dart'; import 'package:sneaker_app/pages/home_page.dart'; import 'package:sneaker_app/pages/item_page.dart'; import 'package:sneaker_app/pages/login_page.dart'; import 'package:sneaker_app/pages/signup_page.dart'; import 'package:sneaker_app/routes/app_route_constants.dart'; import 'package:sneaker_app/services/auth_service.dart'; class MyAppRouter { static final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); // 改为接收AuthService实例,实现状态监听 static GoRouter router(AuthService authService) { return GoRouter( navigatorKey: navigatorKey, // 根据当前用户状态动态设置初始路由 initialLocation: authService.user != null ? "/" : "/login", routes: [ GoRoute( name: MyAppRouteConstants.homeRouteName, path: "/", builder: (context, state) => HomePage()), GoRoute( name: MyAppRouteConstants.itemRouteName, path: "/item/:id", builder: (context, state) { ShopeeTile item = state.extra as ShopeeTile; return ItemPage( id: int.parse(state.pathParameters["id"]!), item: item, ); }), GoRoute( name: MyAppRouteConstants.loginRouteName, path: "/login", builder: (context, state) => LoginPage()), GoRoute( name: MyAppRouteConstants.signupRouteName, path: "/signup", builder: (context, state) => SignupPage()), ], // 移除async修饰符,修正重定向逻辑 redirect: (BuildContext context, GoRouterState state) { final bool loggedIn = authService.user != null; final bool loggingIn = state.matchedLocation == "/login"; final bool signingUp = state.matchedLocation == "/signup"; print("Redirect!"); // 未登录时允许访问登录、注册页,其他页面跳转登录 if (!loggedIn) { if (loggingIn || signingUp) return null; return "/login"; } // 已登录时在登录页则跳转首页 if (loggingIn) return "/"; return null; }, // 监听AuthService状态变化,自动触发重定向 refreshListenable: authService, ); } }
3. 修改main.dart
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:sneaker_app/models/cart.dart'; import 'package:sneaker_app/routes/app_route_config.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:sneaker_app/services/auth_service.dart'; import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider<Cart>(create: (context) => Cart()), ChangeNotifierProvider<AuthService>(create: (context) => AuthService()) ], // 通过Consumer获取AuthService实例,绑定路由与状态 child: Consumer<AuthService>( builder: (context, authService, child) { // 同步FirebaseAuth状态到AuthService FirebaseAuth.instance.authStateChanges().listen((User? user) { print("authState changes"); authService.setUser(user); }); return MaterialApp.router( debugShowCheckedModeBanner: false, theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.grey)), routerConfig: MyAppRouter.router(authService), ); }, ), ); } }
验证修改效果
- 点击登录页的"Sign up"按钮,可正常跳转到注册页,
"Redirect!"打印语句会触发 - 用户登录后,
authStateChanges会触发,"authState changes"打印语句输出,同时自动跳转到首页 - 未登录时访问首页会被重定向到登录页;已登录时访问登录页会被重定向到首页
内容的提问来源于stack exchange,提问作者khoaoaoaoa
相关产品推荐
相关产品推荐

