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

Flutter中QuickAlert弹窗内Navigator导航失败问题求助

解决Flutter中QuickAlert确认按钮导航时的!_debugLocked断言错误

问题场景

在MaterialApp深层的ItemDetailsScreen页面中,调用BLE控制器的onBleStatusChange方法弹出QuickAlert弹窗,点击确认按钮尝试导航到MyNextScreen时,触发以下断言错误:

======== Exception caught by scheduler library =====================================================
The following assertion was thrown during a scheduler callback:
'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4475 pos 12: '!_debugLocked': is not true.
...(省略栈信息)

尝试过添加Future.delayed(Duration.zero)、抽离导航函数、传递BuildContext或使用GetX的Get.to()导航,均未解决问题。

相关代码片段:

class ItemDetailsScreen extends StatefulWidget {
  ItemDetailsScreen();

  @override
  State<ItemDetailsScreen> createState() => _ItemDetailsScreenState();
}

class _ItemDetailsScreenState extends State<ItemDetailsScreen> {
  @override
  Widget build(BuildContext context) {
    // 注意:此处直接在build中调用可能导致重复弹窗
    bleController.onBleStatusChange('box_is_open', context);
    
    return Scaffold(....);
  } 
}

Future<void> onBleStatusChange() async {
  // ...其他逻辑
  QuickAlert.show(
    context: context,
    type: QuickAlertType.success,
    title: 'Box geöffnet!',
    text: 'Bitte entnimm jetzt das Item',
    confirmBtnText: 'Weiter',
    onConfirmBtnTap: () {
      Navigator.of(context).push(
          MaterialPageRoute(
              builder: (context) => const MyNextScreen())); // 触发错误
    }
  );
}

问题原因

这个错误的核心是:在Flutter框架的绘制锁定阶段(比如弹窗关闭的动画过程中)尝试执行导航操作。QuickAlert的确认按钮默认会先触发弹窗关闭的动画,此时Navigator处于锁定状态(_debugLocked为true),直接调用push会违反断言约束。

解决方案

方案1:确保弹窗完全关闭后再执行导航

手动关闭弹窗后,通过WidgetsBinding.addPostFrameCallback或Future.microtask延迟导航,确保弹窗关闭的动画完成、Navigator解锁后再执行操作:

QuickAlert.show(
  context: context,
  type: QuickAlertType.success,
  title: 'Box geöffnet!',
  text: 'Bitte entnimm jetzt das Item',
  confirmBtnText: 'Weiter',
  onConfirmBtnTap: () {
    // 先关闭当前QuickAlert弹窗
    Navigator.pop(context);
    // 在当前帧绘制完成后执行导航
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Navigator.of(context).push(
        MaterialPageRoute(builder: (_) => const MyNextScreen())
      );
    });
  }
);

或者使用Future.microtask:

onConfirmBtnTap: () {
  Navigator.pop(context);
  Future.microtask(() {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (_) => const MyNextScreen())
    );
  });
}

方案2:使用GetX导航的适配写法

如果项目用GetX,同样需要等待弹窗关闭后再调用导航:

onConfirmBtnTap: () {
  Navigator.pop(context); // 关闭QuickAlert
  Future.microtask(() {
    Get.to(() => const MyNextScreen());
  });
}

额外优化:避免在build中重复触发弹窗

原代码中直接在build方法调用bleController.onBleStatusChange,会导致页面重建时重复弹窗,建议将该调用移到initState中:

@override
void initState() {
  super.initState();
  // 延迟到第一帧绘制完成后调用,避免context未就绪问题
  WidgetsBinding.instance.addPostFrameCallback((_) {
    bleController.onBleStatusChange('box_is_open', context);
  });
}

@override
Widget build(BuildContext context) {
  return Scaffold(....);
}

内容的提问来源于stack exchange,提问作者Boommeister

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:55:20