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

使用auto_route实现路由守卫时登录后跳转空白页问题咨询

auto_route路由守卫工作原理与问题解决

工作原理

auto_route的路由守卫会在目标路由被加入导航栈之前触发onNavigation回调,你可以在这个回调里做权限校验:

  • 调用resolver.next(true):校验通过,目标路由正常入栈完成导航
  • 调用resolver.next(false):校验不通过,中断本次导航
  • 也可以在校验不通过时跳转其他路由(比如登录页),后续再根据操作结果决定是否放行原导航请求

问题根因

你的代码存在3个核心问题导致登录后跳转异常:

  1. AuthGuard的isAuthenticated是构造函数传入的固定值,没有和AuthService的实时状态绑定,守卫永远拿的是初始化时的认证状态,登录后状态更新守卫感知不到
  2. AuthGuard的else分支逻辑错误:调用router.push(LoginRoute())之后立刻执行router.popForced(),会把刚入栈的登录页弹掉,最终导致路由栈为空出现空白页
  3. 登录后用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:57:03