热重载触发Dart未处理异常:'!_debugLocked'断言失败求助
!_debugLocked断言错误的解决办法 这个问题我之前也碰到过!你遇到的Dart Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4041 pos 12: '!_debugLocked': is not true错误,本质是在Navigator处于锁定状态(比如热重载触发全局组件重建、当前帧正在执行build操作)时,代码里调用了导航操作(Navigator.push/Navigator.pop这类方法),触发了框架的安全断言。
先把你的错误日志贴出来方便对照:
[VERBOSE-2:shell.cc(210)] Dart Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4041 pos 12: '!_debugLocked': is not true., stack trace: #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39) #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5) #2 NavigatorState.build (package:flutter/src/widgets/navigator.dart:4041:12) #3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28) #4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15) #5 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11) #6 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5) #7 StatefulElement.update (package:flutter/src/widgets/framework.dart:4832:5) #8 Element.updateChild (package:flutter/src/widgets/framework.dart:3314:15) #9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16) #<…> 已重载1237个库中的46个,耗时575ms。
下面给你几个实用的解决思路:
把导航操作延迟到当前帧构建完成后
用WidgetsBinding.instance.addPostFrameCallback包裹你的导航逻辑,这样就能确保代码在当前所有组件都构建完成、Navigator解锁后再执行导航:// 示例:延迟执行push操作 WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).push(MaterialPageRoute(builder: (_) => TargetScreen())); });绝对不要在
build方法里直接写导航逻辑build方法的职责只是构建UI,每次热重载都会重新执行它。如果你的导航逻辑是在build里触发的(比如根据某个状态变量判断后跳转),一定要把这段逻辑移到initState(同样要加延迟)、didChangeDependencies或者用户交互事件(比如按钮点击回调)里。用
SchedulerBinding调度导航任务
另一种延迟执行的方式是用SchedulerBinding,可以指定任务优先级,确保导航操作在合适的时机执行:import 'package:flutter/scheduler.dart'; // 示例:延迟执行pop操作 SchedulerBinding.instance.scheduleTask(() { Navigator.pop(context); }, Priority.animation);检查热重载触发的状态变化
如果是热重载后某个状态变量的变化触发了导航,记得给逻辑加个判断条件,避免每次热重载都重复触发导航,比如用一个布尔标记控制只执行一次:bool _hasNavigated = false; @override void didChangeDependencies() { super.didChangeDependencies(); if (!_hasNavigated && someCondition) { _hasNavigated = true; WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).push(...); }); } }
内容的提问来源于stack exchange,提问作者Code Hunter

