使用go_router包时热重载触发路由异常回退的未知行为问题
问题原因
热重载触发路由回退不是go_router本身的bug,也不是cubit鉴权逻辑的问题,核心原因是GoRouter实例被重复创建:
你把GoRouter改造成接收auth cubit的函数后,一般都是在build方法里调用这个函数生成路由实例——每次热重载都会触发Flutter组件重建,每次重建都会生成一个全新的GoRouter对象,新对象的路由栈会被初始化,直接执行初始重定向逻辑,自然就把你之前push进去的注册页清掉,跳回重定向规则指定的登录页了。
修复步骤
按下面两点调整即可,不需要改现有路由配置和鉴权逻辑:
- 持久持有GoRouter实例,不要在build方法里重复创建
不要在build阶段临时调用构造函数生成GoRouter,把实例初始化逻辑移到组件生命周期的初始化阶段(比如initState),全局只保留一个GoRouter实例:
class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 持久持有路由实例,组件重建时不会重新生成 late final GoRouter appRouter; @override void initState() { super.initState(); // 初始化时传入auth cubit实例,只执行一次 appRouter = createAppRouter(context.read<AuthCubit>()); } @override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: appRouter, // 其他MaterialApp配置不变 ); } }- 持久持有GoRouter实例,不要在build方法里重复创建
- 用
refreshListenable绑定鉴权状态监听,不要靠重建路由触发重定向
go_router原生提供了状态变化监听机制,不需要通过重建路由实例来响应鉴权状态变化:把auth cubit的流包装成可监听对象传给refreshListenable参数,cubit状态变化时会自动触发重定向逻辑,完全不影响现有路由栈。
路由构造函数改造示例:
import 'package:go_router/go_router.dart'; GoRouter createAppRouter(AuthCubit authCubit) { return GoRouter( initialLocation: '/login', // 监听cubit状态变化,自动触发重定向 refreshListenable: GoRouterRefreshStream(authCubit.stream), redirect: (context, state) { final currentAuthState = authCubit.state; final currentPath = state.matchedLocation; // 未登录状态下,允许访问登录、注册页,不要强制跳转 if (currentAuthState is AuthUnauthenticated) { if (currentPath == '/login' || currentPath == '/register') { return null; } return '/login'; } // 已登录状态直接进首页 if (currentAuthState is AuthAuthenticated) { return '/home'; } return null; }, routes: [ // 原有的home、login、register路由配置保持不变 ], ); }- 用
验证
调整完成后,从登录页push进入注册页,修改注册页代码触发热重载,路由栈不会被重置,不会自动回退到登录页;登录、退出登录触发的鉴权重定向逻辑也能正常运行。
内容的提问来源于stack exchange,提问作者Miguel Yurivilca
相关产品推荐
相关产品推荐

