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

Flutter GoRouter同路由栈传递不同extra参数的解决方案

解决GoRouter嵌套路由不同类型Extra参数冲突问题

错误原因分析

你遇到的类型转换错误,本质是跳转嵌套子路由时,父路由的state.extra被意外替换为子路由传入的NewProposalBloc实例,导致父路由中state.extra as Trip的类型转换失败。这是因为当父路由和子路由共用同一个parentNavigatorKey时,GoRouter会覆盖整个路由栈的上下文参数,引发类型冲突。

最优解决方案:利用Bloc上下文传递(无需Extra传参)

既然NewProposalBloc是在NewProposalPage1中创建的,直接通过Bloc的上下文传递即可,无需借助extra,同时确保子路由嵌套在父路由的栈中:

  1. 修改路由定义
    移除子路由的parentNavigatorKey,让子路由归属于父路由的导航栈,同时删除子路由对extra的依赖:
GoRoute(
  path: '/new-proposal-page1',
  parentNavigatorKey: _rootNavigatorKey,
  pageBuilder: (context, state) => CupertinoPage(
    child: NewProposalPage1(trip: state.extra as Trip),
  ),
  routes: [
    GoRoute(
      path: 'new-proposal-page2',
      // 移除parentNavigatorKey,确保子路由在父路由栈中
      pageBuilder: (context, newProposalState) => const CupertinoPage(
        child: NewProposalPage2(),
      ),
    ),
  ]
),
  1. 在子页面中获取Bloc实例
    在NewProposalPage2中直接通过上下文获取父页面提供的NewProposalBloc:
class NewProposalPage2 extends StatelessWidget {
  const NewProposalPage2({super.key});

  @override
  Widget build(BuildContext context) {
    // 从上下文直接获取Bloc实例
    final newProposalBloc = BlocProvider.of<NewProposalBloc>(context);
    
    return BlocProvider.value(
      value: newProposalBloc,
      child: // 你的页面内容
    );
  }
}
  1. 父页面跳转逻辑
    跳转子路由时无需传递extra,直接使用相对路径:
// 在NewProposalPage1中触发跳转
context.push('new-proposal-page2');

备选方案:隔离父路由参数(保留Extra传参)

如果一定要通过extra给子路由传参,可以将父路由的Trip参数保存到页面状态中,避免依赖state.extra的动态变化:

  1. 修改NewProposalPage1
class NewProposalPage1 extends StatefulWidget {
  final Trip trip;
  const NewProposalPage1({super.key, required this.trip});

  @override
  State<NewProposalPage1> createState() => _NewProposalPage1State();
}

class _NewProposalPage1State extends State<NewProposalPage1> {
  late final NewProposalBloc _bloc;

  @override
  void initState() {
    super.initState();
    // 使用widget.trip初始化Bloc,而非依赖state.extra
    _bloc = NewProposalBloc(trip: widget.trip);
  }

  @override
  void dispose() {
    _bloc.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider.value(
      value: _bloc,
      child: Scaffold(
        // 跳转时传递Bloc作为extra
        floatingActionButton: FloatingActionButton(
          onPressed: () => context.push('new-proposal-page2', extra: _bloc),
        ),
      ),
    );
  }
}
  1. 子路由保留原定义
    此时父路由的state.extra as Trip仅在页面初始化时执行一次,后续即使extra被替换为Bloc,页面已通过widget.trip保存了原始参数,不会触发类型转换错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:40:38