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

Flutter加载对话框无法关闭问题求助及代码排查

解决Flutter中加载对话框无法关闭且上下文错误的问题

嘿,我看你遇到了加载对话框关不掉还报上下文错误的问题,这其实是因为你用了已经被销毁的上下文来管理加载对话框,还有GlobalKey的使用方式不对导致的。咱们一步步来解决:

问题根源

  1. 失效的上下文传递:你在关闭AlertDialog的时候,用的是dialogcontext(属于AlertDialog的上下文),然后把这个已经被销毁的context传给了_submit方法,用来显示加载对话框。这就导致后续操作的上下文已经不稳定,触发了那个"Looking up a deactivated widget's ancestor is unsafe"的错误。
  2. GlobalKey的不可靠性:依赖_keyLoader来获取加载对话框的上下文是有风险的,因为当widget树更新或对话框被销毁时,这个key对应的context可能已经失效,导致无法正确关闭对话框。

修复方案

咱们直接去掉GlobalKey,改用当前有效的上下文来管理加载对话框的弹出和关闭,同时修正上下文传递的问题:

1. 修改_handleSubmit中的Ok按钮逻辑

把传给_submit的上下文改成原来的context(不是AlertDialog的dialogcontext),因为dialogcontext在AlertDialog关闭后就失效了:

onPressed: () async {
  Navigator.of(dialogcontext).pop(); // 先关闭确认对话框
  await _submit(context, id); // 传递原来的有效上下文
},

2. 重构_submit方法,移除GlobalKey

直接在_submit里弹出加载对话框,并用当前上下文来关闭它,同时确保出错时也能关闭对话框:

Future<void> _submit(BuildContext context, int id) async {
  // 弹出加载对话框
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext dialogContext) {
      return WillPopScope(
        onWillPop: () async => false, // 禁止返回键关闭
        child: SimpleDialog(
          children: [
            Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation<Color>(Colors.pinkAccent[400]),
                  ),
                  SizedBox(height: 10),
                  Text(
                    "Please Wait...",
                    style: TextStyle(color: Colors.pinkAccent[400]),
                  )
                ],
              ),
            )
          ],
        ),
      );
    },
  );

  try {
    // 调用数据获取方法
    await getData(id, context);
    // 关闭加载对话框,使用rootNavigator确保能正确弹出
    Navigator.of(context, rootNavigator: true).pop();
  } catch (error) {
    print(error);
    // 出错时也要关闭对话框,避免一直显示
    Navigator.of(context, rootNavigator: true).pop();
  }
}

3. (可选)简化Dialogs类

如果你还想保留Dialogs工具类,可以修改它让它不需要GlobalKey,直接用上下文来管理:

class Dialogs {
  static Future<void> showLoadingDialog(
    BuildContext context, String textToShow) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext dialogContext) {
        return WillPopScope(
          onWillPop: () async => false,
          child: SimpleDialog(
            children: <Widget>[
              Center(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    CircularProgressIndicator(
                      valueColor: AlwaysStoppedAnimation<Color>(Colors.pinkAccent[400]),
                    ),
                    SizedBox(height: 10),
                    Text(
                      textToShow,
                      style: TextStyle(color: Colors.pinkAccent[400]),
                    )
                  ],
                ),
              )
            ],
          ),
        );
      },
    );
  }
}

然后在_submit里这样用:

Future<void> _submit(BuildContext context, int id) async {
  await Dialogs.showLoadingDialog(context, "Please Wait...");
  try {
    await getData(id, context);
    Navigator.of(context, rootNavigator: true).pop();
  } catch (error) {
    print(error);
    Navigator.of(context, rootNavigator: true).pop();
  }
}

关键注意点

  • 永远不要传递已经被销毁的widget上下文(比如对话框关闭后的上下文)给后续操作。
  • 避免用GlobalKey来管理对话框的上下文,直接使用当前有效的BuildContext更可靠。
  • 一定要在catch块里也关闭加载对话框,防止出错后对话框一直停留在界面上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:47:48