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

Flutter Beamer如何从两个不同位置跳转至同一页面并解决重复key异常

错误原因

这个报错是Flutter导航栈的固有规则限制:同一个Navigator的页面栈中不允许存在两个key完全相同的Page对象。触发问题的核心诱因有两个:

  1. 你的LandingLocation代码存在语法疏漏:pathBlueprints数组中的/login、/registration后面没有加逗号,Dart会自动拼接相邻字符串,最终这个数组实际只有一个值/login/registration/contactUs,导致/contactUs路径无法正确匹配到LandingLocation。
  2. 当你在底部导航页(当前激活的是NavigationLocation)跳转/contactUs时,Beamer找不到匹配的BeamLocation,就会复用当前的NavigationLocation构建页面栈。而NavigationLocation的buildPages方法会先执行LandingLocation的构建逻辑,检测到路径存在contactUs片段就会插入对应页面,加上你判断页面是否插入用的是pathSegments.contains(只要路径任意段包含对应字符串就会触发插入,没有校验层级),最终导致同一个contactUs的BeamPage被重复插入到栈中,触发key重复报错。

解决步骤

  1. 修复基础语法错误
    给LandingLocation的pathBlueprints数组元素补全逗号:
class LandingLocation extends BeamLocation {
  @override
  List<String> get pathBlueprints => [
    '/login',
    '/registration',
    '/contactUs',
  ];
  // 其余代码保持不变
}
  1. 优化页面插入判断逻辑
    把原来的模糊匹配contains改成精准匹配完整路径,避免深层路径误触发页面插入:
// 仅匹配根路径下的对应页面
if (state.uri.path == '/login')
  BeamPage(
    key: ValueKey('login'),
    child: LoginPage(),
  ),
if (state.uri.path == '/registration')
  BeamPage(
    key: ValueKey('registration'),
    child: RegistrationPage(),
  ),
if (state.uri.path == '/contactUs')
  BeamPage(
    key: ValueKey('contactUs'),
    child: ContactUsPage(),
  ),
  1. 调整跳转逻辑,二选一即可

方案A:跳转时重置页面栈为根路径层级

如果希望打开联系我们页面时不显示底部导航栏,直接覆盖整个页面,把底部导航页的跳转代码改成直接指定BeamLocation,确保页面栈被正确替换:

onPressed: () => context.beamTo(LandingLocation(path: '/contactUs')),

方案B:适配底部导航栈结构

如果希望打开联系我们页面时底部导航栏保持显示,就把导航层级的联系我们路径加到NavigationLocation配置中,单独设置不重复的key:

class NavigationLocation extends BeamLocation {
  @override
  List<String> get pathBlueprints => [
        '/navigation',
        '/navigation/notifications',
        '/navigation/profile',
        '/navigation/contactUs',
    ];

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) => [
        ...LandingLocation().buildPages(context, state),
        if (state.uri.pathSegments.contains('navigation'))
          BeamPage(
            key: ValueKey('navigation'),
            child: NavigationPage(),
          ),
        if (state.uri.pathSegments.contains('notifications'))
          BeamPage(
            key: ValueKey('notifications'),
            child: NotificationsPage(),
          ),
        if (state.uri.pathSegments.contains('profile'))
          BeamPage(
            key: ValueKey('profile'),
            child: ProfilePage(),
          ),
        // 新增导航层级下的联系我们配置
        if (state.uri.path == '/navigation/contactUs')
          BeamPage(
            key: ValueKey('navigation-contactUs'),
            child: ContactUsPage(),
          ),
      ];
}

对应底部导航页的跳转代码改成:

onPressed: () => context.beamToNamed('/navigation/contactUs'),

修改完成后两个位置的跳转都可以正常运行,不会再触发key重复报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:09:03