如何在Go Router中根据认证状态重定向且保留导航状态?
解决方案:Go Router 保留导航状态实现登录后恢复页面
要解决后台自动登出后登录回到原页面的问题,核心是持久化保存登出前的导航栈,登录成功后再恢复这个栈。结合Riverpod和Go Router,具体实现步骤如下:
1. 持久化存储导航路径
用SharedPreferences保存用户登出前的导航栈路径,避免状态刷新丢失。先创建一个Provider提供SharedPreferences实例:
final sharedPreferencesProvider = FutureProvider<SharedPreferences>((ref) async { return await SharedPreferences.getInstance(); });
2. 在Go Router的重定向逻辑中处理状态
通过Go Router的redirect回调,结合Riverpod的authStateProvider,实现:
- 未登录且不在登录页时,保存当前导航路径并重定向到登录页
- 登录成功后,从存储中读取路径并恢复导航栈
final routerProvider = Provider<GoRouter>((ref) { final authState = ref.watch(authStateProvider); final prefsAsync = ref.watch(sharedPreferencesProvider); return GoRouter( initialLocation: authState ? '/home' : '/auth', redirect: (context, state) async { final prefs = await prefsAsync; final isLoggedIn = authState; final currentLocation = state.location; final isOnAuthPage = currentLocation == '/auth'; // 未登录且不在登录页:保存当前路径,跳登录页 if (!isLoggedIn && !isOnAuthPage) { // 提取完整导航栈的路径片段,比如 "/home/detail/profile" -> ["home", "detail", "profile"] final routeSegments = currentLocation.split('/').where((seg) => seg.isNotEmpty).toList(); await prefs.setStringList('saved_nav_routes', routeSegments); return '/auth'; } // 已登录但在登录页:恢复之前的路径,或默认跳首页 if (isLoggedIn && isOnAuthPage) { final savedRoutes = prefs.getStringList('saved_nav_routes') ?? ['home']; final restorePath = '/' + savedRoutes.join('/'); // 清空保存的路径,避免重复恢复 await prefs.remove('saved_nav_routes'); return restorePath; } return null; }, routes: [ GoRoute( path: '/auth', builder: (context, state) => const AuthPage(), ), GoRoute( path: '/home', builder: (context, state) => const HomePage(), routes: [ GoRoute( path: 'detail', builder: (context, state) => const DetailPage(), routes: [ GoRoute( path: 'profile', builder: (context, state) => const ProfilePage(), ), ], ), ], ), ], ); });
3. 处理后台返回的自动登出
监听应用从后台返回的事件,触发登出逻辑(根据你的业务需求调整触发时机):
class MyApp extends ConsumerWidget { const MyApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { WidgetsBinding.instance.addObserver( LifecycleEventHandler( resumeCallBack: () { // 应用从后台回到前台,触发自动登出 ref.read(authStateProvider.notifier).state = false; }, ), ); return MaterialApp.router( routerConfig: ref.watch(routerProvider), ); } } // 自定义生命周期监听类 class LifecycleEventHandler extends WidgetsBindingObserver { final VoidCallback? resumeCallBack; LifecycleEventHandler({this.resumeCallBack}); @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.resumed) { resumeCallBack?.call(); } } }
关键注意事项
- 避免循环重定向:判断当前页面是否为登录页,防止未登录时反复重定向
- 清空保存路径:登录恢复后删除存储的路径,避免下次登录重复恢复旧路径
- 路径格式处理:确保保存和恢复的路径片段拼接正确,过滤空片段
内容的提问来源于stack exchange,提问作者badboy_018
相关产品推荐
相关产品推荐

