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

GoRouter Web端热重载时Extra丢失致应用异常,如何解决?

问题描述

我定义了如下GoRouter路由:

GoRoute(
  path: Screen.classDetail.path,
  builder: (context, state) => AdminClassScreen(
    classItem: state.extra as Class,
  ),
),

通过以下方式导航到该路由:

router.push(Screen.classDetail.path, extra: extra);

在Web端执行热重载时,传入的extra对象不会被保留,导致应用进入异常状态。请问有什么可行的解决办法?

解决办法

方案1:将数据编码到路由路径/查询参数中

把Class对象的关键标识(比如ID)放到路径参数或查询参数里,热重载后通过标识重新从数据源(API、本地缓存等)获取完整数据,彻底摆脱对extra的依赖。

修改路由定义:

GoRoute(
  path: '${Screen.classDetail.path}/:classId',
  builder: (context, state) {
    final classId = state.pathParameters['classId']!;
    // 从数据源获取Class对象,示例为模拟方法
    final classItem = fetchClassById(classId);
    return AdminClassScreen(classItem: classItem);
  },
),

导航时传递ID而非完整对象:

router.push('${Screen.classDetail.path}/${extra.id}');

方案2:用全局状态管理临时存储数据

将需要传递的Class对象存入全局状态容器(如Provider、Riverpod、Bloc),导航时仅跳转路由,页面从全局状态中读取数据。热重载后全局状态通常会保留,避免数据丢失。

以Riverpod为例:

  1. 定义临时状态Provider:
final tempClassProvider = StateProvider<Class?>((ref) => null);
  1. 导航前存入状态:
ref.read(tempClassProvider.notifier).state = extra;
router.push(Screen.classDetail.path);
  1. 路由页面获取数据:
GoRoute(
  path: Screen.classDetail.path,
  builder: (context, state) {
    final classItem = ref.watch(tempClassProvider)!;
    // 页面加载后清空临时状态,防止污染其他场景
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ref.read(tempClassProvider.notifier).state = null;
    });
    return AdminClassScreen(classItem: classItem);
  },
),

方案3:自定义路由extra缓存

创建全局缓存类保存路由extra数据,热重载后优先从缓存读取, fallback 到state.extra。

  1. 实现缓存类:
class RouteExtraCache {
  static final RouteExtraCache _instance = RouteExtraCache._();
  RouteExtraCache._();
  factory RouteExtraCache() => _instance;

  final Map<String, dynamic?> _cache = {};

  void save(String path, dynamic extra) => _cache[path] = extra;
  dynamic? get(String path) => _cache[path];
}
  1. 导航时保存extra:
RouteExtraCache().save(Screen.classDetail.path, extra);
router.push(Screen.classDetail.path, extra: extra);
  1. 修改路由builder:
GoRoute(
  path: Screen.classDetail.path,
  builder: (context, state) {
    final classItem = state.extra as Class? 
        ?? RouteExtraCache().get(Screen.classDetail.path) as Class;
    return AdminClassScreen(classItem: classItem);
  },
),

内容的提问来源于stack exchange,提问作者Michael Jajou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:20:21