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

如何用GoRouter结合Bloc判断用户认证状态并跳转至对应页面

解决方案

1. 实现可监听的登录状态

先创建一个状态管理类,用来跟踪登录状态并通知路由更新:

class AuthState extends ChangeNotifier {
  bool _isLoggedIn = false;
  bool get isLoggedIn => _isLoggedIn;

  void login() {
    _isLoggedIn = true;
    notifyListeners();
  }

  void logout() {
    _isLoggedIn = false;
    notifyListeners();
  }
}

2. 修改GoRouter配置,添加重定向逻辑

在路由配置中加入redirect规则和状态监听,根据登录状态自动跳转:

final AuthState _authState = AuthState();

GoRouter router() {
  return GoRouter(
    debugLogDiagnostics: true,
    refreshListenable: _authState, // 监听登录状态变化,自动触发重定向
    redirect: (context, state) {
      final isLoggedIn = _authState.isLoggedIn;
      final isOnLoginPage = state.location == Routes.logIn.path;

      // 未登录且不在登录页,强制跳转到登录页
      if (!isLoggedIn && !isOnLoginPage) {
        return Routes.logIn.path;
      }
      // 已登录且在登录页,跳转到ShellRoute的首页
      if (isLoggedIn && isOnLoginPage) {
        return Routes.home.path;
      }
      // 其他情况保持原路由
      return null;
    },
    routes: _routes,
  );
}

List<RouteBase> get _routes => <RouteBase>[
      GoRoute(
        name: Routes.logIn.name,
        path: Routes.logIn.path,
        builder: (context, state) {
          return LogInScreen(
            onLoginSuccess: () => _authState.login(), // 登录成功后更新状态
          );
        },
      ),
      ShellRoute(
        navigatorKey: _shellNavigatorKey,
        builder: (context, state, child) {
          return MainScreen(child: child);
        },
        routes: <RouteBase>[
          GoRoute(
            path: Routes.home.path,
            name: Routes.home.name,
            builder: (_, __) => const HomeScreen(),
          ),
          // 可在此添加更多底部导航对应的子路由
        ],
      ),
    ];

3. 优化MyApp的Router实例复用

避免每次build都创建新的GoRouter实例,防止状态丢失:

final _appRouter = router();

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      builder: (_, __) => MaterialApp.router(
        routerConfig: _appRouter,
        theme: AppTheme.lightTheme,
      ),
    );
  }
}

4. 登录页触发状态更新

在LogInScreen中完成登录逻辑后,调用状态更新方法:

class LogInScreen extends StatelessWidget {
  final VoidCallback onLoginSuccess;
  
  const LogInScreen({super.key, required this.onLoginSuccess});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 模拟登录接口请求
            Future.delayed(const Duration(seconds: 1), () {
              onLoginSuccess();
            });
          },
          child: const Text('登录'),
        ),
      ),
    );
  }
}

核心逻辑说明

  • redirect函数会在每次路由跳转前执行,根据登录状态动态调整跳转目标
  • refreshListenable监听AuthState的变化,登录状态更新时会自动重新执行重定向逻辑
  • 无需直接跳转ShellRoute本身,跳转到它的子路由(如Routes.home.path)就会自动加载ShellRoute对应的MainScreen容器

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 21:35:24