Flutter中GoRouter的refreshListenable与redirect属性使用问题
解决方案
1. 修正TokenNotifier的状态管理
优化状态操作方法,新增重置逻辑,避免后续重定向循环:
final invalidTokenProvider = ChangeNotifierProvider<TokenNotifier>((ref) => TokenNotifier()); class TokenNotifier extends ChangeNotifier { bool _invalidToken = false; bool get invalidToken => _invalidToken; void setInvalidToken(bool value) { _invalidToken = value; notifyListeners(); } // 重定向完成后重置状态,防止重复触发 void resetInvalidToken() { _invalidToken = false; notifyListeners(); } }
2. 修复GoRouter的监听与重定向逻辑
调整refreshListenable的获取方式,完善重定向判断逻辑,避免循环跳转:
GoRouter buildGoRouter(WidgetRef ref) { final tokenNotifier = ref.read(invalidTokenProvider.notifier); return GoRouter( routes: $appRoutes, initialLocation: '/', navigatorKey: rootNavigatorKey, // 直接传入ChangeNotifier实例作为监听对象 refreshListenable: tokenNotifier, redirect: (context, state) { final isTokenInvalid = ref.read(invalidTokenProvider).invalidToken; final currentPath = state.location; // 仅在token无效且当前不在目标页时触发重定向 if (isTokenInvalid && currentPath != '/') { tokenNotifier.resetInvalidToken(); return '/'; } return null; }, ); }
3. 调整HTTP客户端的状态触发代码
改用read获取notifier,避免不必要的状态监听:
final response = await http.Response.fromStream(await request.send()); if (response.statusCode == 401 || response.body.contains("FST_JWT_AUTHORIZATION_TOKEN_INVALID")) { getLogout(_ref.read(boxProvider)); _ref.read(invalidTokenProvider.notifier).setInvalidToken(true); } return response;
关键问题说明
- refreshListenable错误:原代码用
ref.watch获取notifier会触发多余的状态监听,直接用ref.read获取固定实例,GoRouter才能正确感知notifyListeners()的调用。 - 重定向循环问题:必须判断当前页面是否已在目标路径,同时重定向后重置状态,否则会无限触发跳转逻辑。
- Riverpod状态读取规范:在redirect回调中用
ref.read而非ref.watch,因为该逻辑仅需单次读取状态,无需持续监听。
内容的提问来源于stack exchange,提问作者FrancisMB
相关产品推荐
相关产品推荐

