使用go-router返回页面时如何自动刷新Riverpod状态?
解决方案
方案1:通过页面Key强制重建
GoRouter默认会复用栈中页面的Widget实例,返回时不会触发重建。给目标页面添加动态唯一Key,可强制Flutter创建新的Widget实例,从而重置Riverpod Provider状态。
修改路由定义
class Page1Route extends GoRouteData { const Page1Route({this.refreshToken}); // 可选参数,用于生成唯一Key final String? refreshToken; static const String name = kNamePage1; static const String path = kPathPage1; @override Widget build(BuildContext context, GoRouterState state) { // 用时间戳作为Key的一部分,确保每次导航Key不同 final uniqueKey = refreshToken ?? DateTime.now().millisecondsSinceEpoch.toString(); return Page1Screen(key: ValueKey(uniqueKey)); } }
导航时传入新的refreshToken
从子路由返回Page1时,传入新的token触发重建:
// 从Sub1Page1返回Page1 Page1Route(refreshToken: DateTime.now().toString()).go(context);
方案2:利用RouteObserver监听路由返回事件
通过RouteObserver监听页面从子路由返回的事件,自动重置Provider状态,无需手动调用ref.invalidate。
1. 全局注册RouteObserver
// 全局定义RouteObserver final routeObserver = RouteObserver<ModalRoute<void>>(); // 初始化GoRouter时添加observer GoRouter( routes: $appRoutes, initialLocation: initialLocation, debugLogDiagnostics: true, observers: [routeObserver], );
2. 在页面中监听路由事件
将Page1Screen改为ConsumerStatefulWidget并混入RouteAware:
class Page1Screen extends ConsumerStatefulWidget { const Page1Screen({super.key}); @override ConsumerState<Page1Screen> createState() => _Page1ScreenState(); } class _Page1ScreenState extends ConsumerState<Page1Screen> with RouteAware { @override void didChangeDependencies() { super.didChangeDependencies(); // 订阅路由变化 routeObserver.subscribe(this, ModalRoute.of(context)!); } @override void dispose() { // 取消订阅 routeObserver.unsubscribe(this); super.dispose(); } @override void didPopNext() { // 从子路由返回当前页面时,自动重置目标Provider ref.invalidate(myProvider); } @override Widget build(BuildContext context) { final pageState = ref.watch(myProvider); // 页面UI逻辑 return Scaffold(...); } }
方案3:使用Family Provider绑定路由标识
将Provider定义为Family类型,用路由的动态唯一标识作为参数,确保每次进入页面时获取全新的Provider实例。
定义Family Provider
final myProvider = StateNotifierProvider.family<MyNotifier, MyState, String>((ref, routeId) { final notifier = MyNotifier(); ref.onDispose(notifier.dispose); return notifier; });
在页面中使用Provider
class Page1Screen extends ConsumerWidget { const Page1Screen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // 结合时间戳生成唯一路由标识,确保每次进入页面都创建新Provider final routeId = '${GoRouterState.of(context).uri}_${DateTime.now().millisecondsSinceEpoch}'; final pageState = ref.watch(myProvider(routeId)); // 页面UI逻辑 return Scaffold(...); } }
内容的提问来源于stack exchange,提问作者Madere
相关产品推荐
相关产品推荐

