使用auto_route实现路由守卫时登录后跳转空白页问题咨询
auto_route路由守卫工作原理与问题解决
工作原理
auto_route的路由守卫会在目标路由被加入导航栈之前触发onNavigation回调,你可以在这个回调里做权限校验:
- 调用
resolver.next(true):校验通过,目标路由正常入栈完成导航 - 调用
resolver.next(false):校验不通过,中断本次导航 - 也可以在校验不通过时跳转其他路由(比如登录页),后续再根据操作结果决定是否放行原导航请求
问题根因
你的代码存在3个核心问题导致登录后跳转异常:
- AuthGuard的
isAuthenticated是构造函数传入的固定值,没有和AuthService的实时状态绑定,守卫永远拿的是初始化时的认证状态,登录后状态更新守卫感知不到 - AuthGuard的else分支逻辑错误:调用
router.push(LoginRoute())之后立刻执行router.popForced(),会把刚入栈的登录页弹掉,最终导致路由栈为空出现空白页 - 登录后用
pushRoute跳转首页,登录页依然在栈中,后续退栈会回到登录页,不符合常规交互逻辑
解决步骤
1. 改造AuthGuard,绑定实时认证状态
直接让守卫依赖AuthService实例,每次导航都读取最新的认证状态:
class AuthGuard extends AutoRouteGuard { AuthGuard({required this.authService}); final AuthService authService; @override void onNavigation(NavigationResolver resolver, StackRouter router) { if (authService.isAuthenticated) { resolver.next(true); return; } // 未登录时跳转到登录页,登录完成后再判断是否放行原请求 router.push(LoginRoute(onLoginSuccess: () { resolver.next(authService.isAuthenticated); })); } }
2. 改造LoginPage,支持登录成功回调
给LoginPage增加可选的登录成功回调参数:
class LoginPage extends StatelessWidget { const LoginPage({Key? key, this.onLoginSuccess}) : super(key: key); final VoidCallback? onLoginSuccess; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Login Page'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { context.read<AuthService>().login(); onLoginSuccess?.call(); // 登录成功后替换当前登录页为首页 context.replaceRoute(const HomeRoute()); }, child: const Text('Authenticate Me')), ElevatedButton( onPressed: () { context.pushRoute(const HomeRoute()); }, child: const Text('Go Home')), ], ), ), ); } }
3. 初始化路由时传入绑定了AuthService的守卫
注册AppRouter时要把全局的AuthService实例传给AuthGuard,保证守卫拿的是全局唯一的认证状态:
// main.dart示例 void main() { final authService = AuthService(); runApp( ChangeNotifierProvider.value( value: authService, child: MyApp(authService: authService), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key, required this.authService}); final AuthService authService; @override Widget build(BuildContext context) { final appRouter = AppRouter(authGuard: AuthGuard(authService: authService)); return MaterialApp.router( title: 'AutoRoute Guard Demo', routerDelegate: appRouter.delegate(), routeInformationParser: appRouter.defaultRouteParser(), ); } }
4. (可选)优化登出逻辑
登出后直接跳回登录页,清空路由栈:
// HomePage的登出按钮逻辑 onPressed: () { context.read<AuthService>().logout(); context.replaceAll([const LoginRoute()]); },
排查方法
如果还有问题可以按以下步骤排查:
- 在AuthGuard的onNavigation方法中打印
authService.isAuthenticated的值,确认登录后状态是否正常更新 - 打印路由栈信息,确认跳转后栈内路由是否符合预期
- 检查AppRouter初始化时传入的AuthService实例是否和全局Provider中的实例一致,避免出现多实例状态不同步的问题
内容的提问来源于stack exchange,提问作者Shady Aziza
相关产品推荐
相关产品推荐

