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

Flutter中重复使用MaterialPageRoute跳转页面引发的断言错误问题排查

解决重复跳转MaterialPageRoute时的断言异常问题

这个断言错误的核心原因很明确:你正在重复使用同一个MaterialPageRoute实例。当你第一次把某个路由实例push到Navigator后,这个实例会和当前导航器绑定(_navigator属性被赋值);当你从页面返回时,该路由实例的关联状态并没有被重置,再次尝试push同一个实例就会触发entry.route._navigator == null的断言——因为这个路由已经属于某个Navigator了。

解决方案:每次跳转时创建新的路由实例

我们需要修改代码逻辑,不再预存MaterialPageRoute实例,而是存储页面的构建逻辑,在用户点击时动态创建新的路由实例。

步骤1:修改路由列表的定义

把原来预创建MaterialPageRoute的列表,改成存储页面的构建函数(或者页面组件本身,根据需求调整):

// 存储页面的构建函数,每个函数返回对应的页面组件
List<Widget Function(BuildContext)> lista = [
  (_) => Page1(),
  (_) => Page2(),
];

步骤2:更新_listado函数的逻辑

在用户点击时,动态创建新的MaterialPageRoute实例:

List<Widget> _listado(
    BuildContext context, List<Widget Function(BuildContext)> lista) {
  List<Widget> _listaWidget = [];
  lista.forEach((pageBuilder) {
    _listaWidget.add(GestureDetector(
      onTap: () {
        // 每次点击都生成新的路由实例,避免重复使用
        Navigator.push(
          context,
          MaterialPageRoute(builder: pageBuilder),
        );
      },
      child: Container(
        padding: const EdgeInsets.all(5),
        child: Container(
          padding: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            image: DecorationImage(
              image: Image.asset('assets/images/image1.png').image,
              fit: BoxFit.cover,
            ),
            border: Border.all(
              color: Colors.white,
              width: 2,
            ),
            borderRadius: BorderRadius.circular(20.0),
            boxShadow: [
              BoxShadow(
                color: Colors.white.withOpacity(0.5),
                spreadRadius: 1,
                blurRadius: 3,
                offset: const Offset(4, 4),
              ),
            ],
          ),
        ),
      ),
    ));
  });
  return _listaWidget;
}

步骤3:更新menuGrid函数的参数类型

匹配修改后的路由列表类型:

GridView menuGrid(BuildContext context, List<Widget Function(BuildContext)> lista, int columnas, int border) {
  return GridView.count(
    crossAxisCount: columnas,
    padding: const EdgeInsets.all(20),
    crossAxisSpacing: 10,
    mainAxisSpacing: 10,
    children: <Widget>[
      ..._listado(context, lista),
    ],
  );
}

额外说明

MaterialPageRoute是带有内部状态的对象,它会跟踪自己在导航栈中的位置以及与导航器的关联关系,因此永远不要重复使用同一个路由实例。通过每次点击时创建新实例,就能彻底避免这个断言问题,同时也能保证页面每次跳转时都能正确初始化(比如如果页面有初始化逻辑,每次跳转都会重新执行)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:57:41