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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:35:04