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

如何基于AutoRoute实现Flutter认证状态驱动的声明式导航

实现基于认证状态的AutoRoute声明式导航

核心思路

不需要大幅修改现有AuthCubit,主要通过AutoRoute路由守卫+监听认证状态动态切换初始路由实现需求。以下是分步实现方案:


1. 完善AppRouter路由配置

先确保AppRouter中正确声明目标路由,并且不设置固定初始路由(留给动态逻辑判断):

@MaterialAutoRouter(
  routes: [
    AutoRoute(page: LoginPage, initial: false),
    AutoRoute(page: DashboardPage, initial: false),
    // 其他业务路由按需添加
  ],
)
class AppRouter extends _$AppRouter {}

2. 实现AuthGuard路由守卫

创建AutoRoute的路由守卫,拦截需要登录权限的页面,根据认证状态决定放行或重定向:

@injectable
class AuthGuard extends AutoRouteGuard {
  final AuthCubit _authCubit;

  AuthGuard(this._authCubit);

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    final authState = _authCubit.state;
    if (authState is _IsLoggedIn) {
      // 已登录,允许访问目标页面
      resolver.next(true);
    } else {
      // 未登录,重定向到登录页
      router.push(const LoginRoute());
      resolver.next(false);
    }
  }
}

然后给需要登录权限的路由绑定守卫(比如Dashboard):

@MaterialAutoRouter(
  routes: [
    AutoRoute(page: LoginPage, initial: false),
    AutoRoute(
      page: DashboardPage,
      initial: false,
      guards: [AuthGuard], // 给Dashboard添加登录守卫
    ),
  ],
)
class AppRouter extends _$AppRouter {}

3. 监听认证状态,动态设置初始路由

在应用入口Widget(比如MyApp)中,通过BlocBuilder监听AuthCubit状态,动态决定启动时的初始路由:

class MyApp extends StatelessWidget {
  final AppRouter _appRouter;
  final AuthCubit _authCubit;

  const MyApp({
    super.key,
    required AppRouter appRouter,
    required AuthCubit authCubit,
  })  : _appRouter = appRouter,
        _authCubit = authCubit;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AuthCubit, AuthState>(
      bloc: _authCubit,
      builder: (context, state) {
        // 处理启动时的加载状态(可选,优化用户体验)
        if (state is _Loading) {
          return const Scaffold(body: Center(child: CircularProgressIndicator()));
        }
        
        return MaterialApp.router(
          routerDelegate: _appRouter.delegate(
            initialRoute: state is _IsLoggedIn 
                ? DashboardRoute.name 
                : LoginRoute.name,
          ),
          routeInformationParser: _appRouter.defaultRouteParser(),
        );
      },
    );
  }
}

4. 登录/登出后的路由跳转

在登录成功或登出的逻辑中,更新认证状态后手动切换路由:

// 登录成功示例
await _tokenRepository.saveAccessToken(newAccessToken);
await _tokenRepository.saveRefreshToken(newRefreshToken);
_authStateRepository.setUserLoggedIn(true);
// 跳转到Dashboard,替换当前路由栈
context.router.replace(const DashboardRoute());

// 登出示例
await _tokenRepository.saveAccessToken(null);
await _tokenRepository.saveRefreshToken(null);
_authStateRepository.setUserLoggedIn(false);
// 跳转到Login,替换当前路由栈
context.router.replace(const LoginRoute());

对现有代码的小优化建议

  1. 给AuthState添加加载状态:当前AuthCubit初始状态直接设为isLoggedIn(),但启动时token检查还未完成,建议新增加载状态避免闪屏:
@freezed
class AuthState with _$AuthState {
  const factory AuthState.loading() = _Loading; // 新增加载状态
  const factory AuthState.isLoggedIn() = _IsLoggedIn;
  const factory AuthState.isLoggedOut() = _IsLoggedOut;
}

然后修改AuthCubit构造函数:

AuthCubit(this._authStateRepository) : super(const AuthState.loading()) {
  _init();
}
  1. 合并TokenRepository的检查逻辑:当前_checkForAccessToken和_checkForRefreshToken并行调用,会导致setUserLoggedIn被触发两次,建议只保留refresh token的检查(因为refresh token存在即可证明用户已登录,access token过期可自动刷新):
void _init() {
  _checkForRefreshToken(); // 只检查refresh token
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:15:55