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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:27:40