Flutter调用组件消失时弹框遇_debugLocked错误的解决问询
问题
我有一个带“Add”链接的下拉菜单,通过Navigator.push跳转至创建新下拉元素的表单,常规场景下运行正常。但该下拉菜单关联已连接的蓝牙外设,有时外设断开连接会导致下拉菜单关闭,此时在表单中尝试弹出错误对话框会触发如下错误:
I/flutter (20507): ⚠️ Unhandled Dart error: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4532 pos 12: '!_debugLocked': is not true. I/flutter (20507): ----------------FIREBASE CRASHLYTICS---------------- I/flutter (20507): 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4532 pos 12: '!_debugLocked': is not true. I/flutter (20507): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61) I/flutter (20507): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5) I/flutter (20507): #2 NavigatorState._pushEntry (package:flutter/src/widgets/navigator.dart:4532:12) I/flutter (20507): #3 NavigatorState.push (package:flutter/src/widgets/navigator.dart:4489:5) I/flutter (20507): #4 showDialog (package:flutter/src/material/dialog.dart:1297:65) I/flutter (20507): #5 confirm (package:survey/utilities/widgets/dialog.dart:52:20) I/flutter (20507): #6 _NtripFormState.handleFailedConnection (package:survey/views/ntrip/form.dart:478:18) I/flutter (20507): #7 _NtripFormState._testConnection (package:survey/views/ntrip/form.dart:467:20) I/flutter (20507): <asynchronous suspension> I/flutter (20507): #8 _NtripFormState.testConnection (package:survey/views/ntrip/form.dart:425:12) I/flutter (20507): <asynchronous suspension> I/flutter (20507): #9 _NtripFormState.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:survey/views/ntrip/form.dart:212:54) I/flutter (20507): <asynchronous suspension>
该'!_debugLocked': is not true错误会阻止在一个Navigator.pop执行过程中调用另一个Navigator.pop。_debugLocked是私有变量,且仅在调试模式下触发断言错误,无法在非调试代码中检查该变量或捕获错误。我已尝试用Navigator.canPop包裹Navigator.pop调用,但无法处理嵌套pop的情况。请问是否有办法检测该状态,而非跟踪调用上下文的状态?
解决方案
方法1:延迟到下一帧执行导航操作
利用WidgetsBinding的addPostFrameCallback,把弹窗或导航操作推迟到当前帧渲染完成后执行,避开Navigator的锁定状态:
WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( context: context, builder: (context) => AlertDialog( title: Text('错误'), content: Text('连接失败'), actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text('确定'))], ), ); });
方法2:封装安全的弹窗工具函数
写一个通用函数,通过try-catch捕获调试模式下的断言错误,同时结合延迟执行兜底:
Future<void> safeShowDialog({required BuildContext context, required WidgetBuilder builder}) async { try { await showDialog(context: context, builder: builder); } catch (e) { if (e is AssertionError && e.message.toString().contains('_debugLocked')) { await Future.microtask(() { showDialog(context: context, builder: builder); }); } else { rethrow; } } }
后续直接用这个函数替代原生showDialog即可。
方法3:监听页面生命周期过滤无效操作
在表单页面混入WidgetsBindingObserver,判断页面是否处于活跃状态,仅在活跃时执行弹窗:
class _NtripFormState extends State<NtripForm> with WidgetsBindingObserver { bool _isPageActive = true; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { _isPageActive = state == AppLifecycleState.resumed; } void handleFailedConnection() { if (_isPageActive) { safeShowDialog(context: context, builder: ...); } } }
从根源上避免页面退出时触发导航冲突。
内容的提问来源于stack exchange,提问作者Crag
相关产品推荐
相关产品推荐

