Flutter基于Bloc与go_router实现访客权限及路由跳转问题
解决方案
1. 修复「Multiple widgets used the same GlobalKey」错误
这个问题通常是路由配置中重复使用了同一个GlobalKey导致的,尤其是StatefulShellRoute的key配置容易踩坑:
- 为每个
StatefulShellRoute分配独立的GlobalKey:不要在多个路由或重定向逻辑中复用同一个key,确保每个路由壳的key唯一// 正确示例:为不同路由壳创建独立key final _homeShellKey = GlobalKey<StatefulShellRouteState>(); final _authShellKey = GlobalKey<StatefulShellRouteState>(); // 路由配置中对应使用 StatefulShellRoute( key: _homeShellKey, // 其他配置... ), StatefulShellRoute( key: _authShellKey, // 其他配置... ), - 避免在重定向逻辑中重复生成路由组件:不要在
redirect回调里动态创建带相同key的路由实例,让go_router的路由表统一管理路由组件的创建。
2. 正确实现「登录后返回原受保护路由」逻辑
放弃通过/login/?redirect参数传递路径的方式,改用go_router的路由状态和AuthBloc结合的方案,更稳定且避免key冲突:
优化路由重定向逻辑
在AppRouter的redirect方法中,根据AuthBloc状态和当前路由记录原路径:
String? redirect(BuildContext context, GoRouterState state) { final authState = context.read<AuthBloc>().state; final isLoggedIn = authState is AuthAuthenticated; final isGuest = authState is AuthGuest; // 未完成引导页,强制跳转到引导页 if (authState is AuthInitial && state.location != '/onboarding') { return '/onboarding'; } // 未登录/访客状态访问受保护路由,记录原路径并跳转到登录页 final protectedRoutes = ['/stays-payment']; if (!isLoggedIn && protectedRoutes.contains(state.fullPath)) { context.read<AuthBloc>().add(AuthSetRedirectPath(state.fullPath)); return '/login'; } // 已登录状态访问登录/引导页,跳转到主页 if (isLoggedIn && (state.location == '/login' || state.location == '/onboarding')) { return '/home'; } return null; }
登录成功后跳转回原路径
在AuthBloc的登录成功事件处理中,读取存储的跳转路径并完成跳转:
// AuthBloc事件处理逻辑 on<AuthLoginSuccess>((event, emit) { emit(AuthAuthenticated(user: event.user)); final redirectPath = state.redirectPath ?? '/home'; GoRouter.of(context).go(redirectPath); });
3. 优化BlocListener的路由刷新逻辑
在MyApp的BlocListener中,不要手动触发路由跳转,而是调用go_router的refresh方法更新路由状态,避免重复创建路由组件:
BlocListener<AuthBloc, AuthState>( listener: (context, state) { GoRouter.of(context).refresh(); }, child: MaterialApp.router( routerConfig: AppRouter().router, ), )
额外注意事项
- 确保访客模式下,非受保护路由可正常访问,受保护路由会触发重定向
- 测试全流程:首次进入引导页→访客模式→访问受保护路由→登录→返回原路由,验证逻辑是否通顺
- SharedPreferences存储的状态初始化要正确,避免AuthBloc初始状态错误导致路由异常
内容的提问来源于stack exchange,提问作者Tocklewo
相关产品推荐
相关产品推荐

