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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:58:42