使用Flutter Navigator时出现!_debugLocked is not true报错怎么解决
报错本质:该断言触发是因为Flutter的Navigator正处于帧绘制、路由过渡动画的锁定状态时,被同步触发了新的路由操作(push/pop/replace等),导致操作冲突。
以下是可直接落地的排查修复方案:
- 排查是否在
build方法中直接执行Navigator操作
build执行过程中组件还未完成挂载,此时直接调用路由跳转必然触发锁定冲突,需要将跳转逻辑包裹在帧绘制完成回调中:
// 错误示例 @override Widget build(BuildContext context) { if (loginSuccess) { Navigator.of(context).pushNamed('/home'); } return const Scaffold(); } // 修复后写法 @override Widget build(BuildContext context) { if (loginSuccess) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pushNamed('/home'); }); } return const Scaffold(); }
- 排查是否在弹窗、底部弹窗的关闭回调中同步执行路由操作
弹窗关闭的动画执行过程中Navigator仍处于锁定状态,要么等待弹窗关闭异步完成后再执行跳转,要么包裹帧回调:
// 正确写法1:等待弹窗完全关闭 onPressed: () async { await showDialog( context: context, builder: (context) => AlertDialog( content: const Text('操作成功'), ), ); if (mounted) { Navigator.of(context).pop(); } } // 正确写法2:包裹帧回调 showDialog( context: context, builder: (context) => AlertDialog(), ).then((_) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pushNamed('/next'); }); });
- 排查是否存在连续同步调用多次Navigator操作的逻辑
同一方法内先pop再push、或者同时触发两次路由跳转的场景,两次操作间隔过短会触发锁定,可将第二次操作延迟到下一帧执行:
Navigator.of(context).pop(); // 延迟到下一帧执行第二次路由操作 Future.delayed(Duration.zero, () { if (mounted) { Navigator.of(context).pushNamed('/newPage'); } });
- 排查是否在
NavigatorObserver的回调(didPush/didPop/didReplace等)中直接执行路由操作
这类回调触发时Navigator本身正处于路由处理的锁定状态,同步操作必然触发断言,必须包裹帧回调延迟执行。 - 排查异步回调中的路由操作是否加了
mounted判断
如果异步回调执行时当前页面已经被销毁,Context已经失效,此时执行路由操作也可能偶发该报错,执行跳转前先判断组件是否仍挂载:
onTap: () async { await submitForm(); if (mounted) { Navigator.of(context).pop(); } }
内容的提问来源于stack exchange,提问作者saeed bayat
相关产品推荐
相关产品推荐

