GoRouter子路由传递参数/额外对象的方法及类型错误排查
GoRouter子路由传参方法及Null类型错误解决
一、子路由传递参数的三种常用方式
GoRouter子路由支持多种传参方式,常用的有三种:
- 路径参数:在路由path中定义占位符(如
a/:num),通过state.params获取,适合必填的结构化参数。 - 查询参数:导航时在URL后拼接
?key=value,通过state.queryParams获取,适合可选参数。 - extra对象:通过导航时的
extra字段传递任意类型对象,但返回导航时该字段会被置为null,这也是你报错的核心原因。
二、错误原因
你从PageB导航回PageA时,没有重新传递extra参数,导致state.extra为null。但你直接将其强制转换为Map<String, dynamic>,后续取res['num']赋值给int类型的num时,null无法转换为int,触发类型错误。
三、解决方案
方案1:用路径参数传递(推荐,避免null问题)
修改路由定义,把num设为路径参数,这样参数会被编码到URL中,返回时不会丢失:
final _router = GoRouter( debugLogDiagnostics: true, initialLocation: '/', routes: [ GoRoute( path: '/', builder: (context, state) => TopPage(), routes: [ GoRoute( // 定义路径参数num path: 'a/:num', builder: (context, state) { // 解析参数为int,处理可能的转换失败 final num = int.tryParse(state.params['num'] ?? ''); return PageA( num: num ?? 0, // 给默认值避免null ); }, routes: [ GoRoute( path: 'b', builder: (context, state) { // 从父路由的params中获取numFromA final numFromA = int.tryParse(state.params['num'] ?? ''); return PageB( numFromA: numFromA ?? 0, ); }, ), ], ), ], ), ], );
导航示例:
- 进入PageA:
context.go('/a/123') - 从PageB返回PageA:
context.go('/a/${widget.numFromA}')
方案2:兼容extra为null的情况
如果坚持使用extra,需要在PageA的builder中增加null判断,同时返回时手动传递参数:
// 修改PageA的路由builder GoRoute( path: 'a', builder: (context, state) { // 先判断extra是否为null,再转换类型 final res = state.extra as Map<String, dynamic>?; return PageA( num: res?['num'] as int? ?? 0, // 给默认值防止null ); }, routes: [ GoRoute( path: 'b', builder: (context, state) { final res = state.extra as Map<String, dynamic>?; return PageB( numFromA: res?['numFromA'] as int? ?? 0, ); }, ), ], )
从PageB返回时需重新传递extra:
// PageB中的返回逻辑 context.go('/a', extra: {'num': widget.numFromA});
方案3:状态管理共享参数
如果参数需要在多个页面共享,或者结构复杂,可以用Provider、Riverpod等状态管理工具存储参数,页面直接从状态中读取,无需通过路由传递。
四、关键注意点
extra仅在正向导航时有效,返回导航(pop、go回上一级)不会自动携带,必须手动传递。- 路径/查询参数会被编码到URL,适合简单基本类型;
extra可传复杂对象,但页面重建或热重启时可能丢失数据。
内容的提问来源于stack exchange,提问作者Masahiro Aoki
相关产品推荐
相关产品推荐

