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

Flutter中关闭showModalBottomSheet后点击Snackbar操作触发‘Looking up a deactivated widget's ancestor is unsafe’错误的解决方案咨询

问题分析与解决方案

你遇到的这个错误核心原因很明确:SnackBar的操作按钮使用了已经被销毁的Widget上下文。

当你在CreateFavouriteSuccess分支里先调用ScaffoldMessenger.of(context).showSnackBar(),紧接着执行Navigator.of(context).pop()关闭底部弹窗时,BlocListener所在的整个弹窗Widget会被标记为deactivated(销毁状态)。而SnackBar的SnackBarAction里的context,正是这个已经失效的弹窗Widget的上下文。当你点击操作按钮时,用这个失效的上下文去查找ScaffoldMessenger,就触发了"Looking up a deactivated widget's ancestor"的错误。

下面给你几个简单有效的解决办法:


方案1:提前保存ScaffoldMessenger实例(代码改动最小)

在弹窗Widget还未被销毁时,先获取有效的ScaffoldMessenger实例并保存,后续操作直接调用这个实例,彻底避开对失效上下文的依赖:

else if (state is CreateFavouriteSuccess) {
  // 提前拿到有效的ScaffoldMessenger对象
  final messenger = ScaffoldMessenger.of(context);
  messenger.showSnackBar(
    SnackBar(
      content: AutoSizeText(state.successMessage),
      duration: const Duration(seconds: 3),
      action: SnackBarAction(
        label: kYes,
        onPressed: () {
          // 直接用提前保存的messenger实例操作
          messenger.hideCurrentSnackBar();
        },
      ),
    ),
  );
  Navigator.of(context).pop();
}

方案2:使用全局GlobalKey绑定ScaffoldMessenger

如果你的弹窗是在某个父页面中弹出的,可以通过全局Key直接获取父页面的ScaffoldMessenger,完全脱离弹窗上下文的限制:

  1. 在父页面定义全局Key:
final GlobalKey<ScaffoldMessengerState> _messengerKey = GlobalKey<ScaffoldMessengerState>();
  1. 把Key绑定到父页面的Scaffold:
Scaffold(
  key: _messengerKey,
  // 其他页面内容...
)
  1. 在弹窗的BlocListener中使用这个全局Key:
else if (state is CreateFavouriteSuccess) {
  _messengerKey.currentState?.showSnackBar(
    SnackBar(
      content: AutoSizeText(state.successMessage),
      duration: const Duration(seconds: 3),
      action: SnackBarAction(
        label: kYes,
        onPressed: () {
          _messengerKey.currentState?.hideCurrentSnackBar();
        },
      ),
    ),
  );
  Navigator.of(context).pop();
}

方案3:将SnackBar移到父页面显示

如果你的Bloc是在父页面中提供的,可以调整逻辑,等弹窗关闭后再在父页面显示SnackBar:

// 父页面调用弹窗的代码
await showModalBottomSheet(
  context: context,
  builder: (context) => YourFavouriteFormWidget(),
);
// 弹窗关闭后,在这里显示成功提示
ScaffoldMessenger.of(context).showSnackBar(
  SnackBar(content: AutoSizeText("文件添加成功")),
);

这种方法需要你调整状态触发逻辑,比如在弹窗中完成操作后,通过Bloc状态通知父页面显示SnackBar。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:58:13