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
相关产品推荐
相关产品推荐

