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

如何结合notifyListeners()与变量变更正确调用setState并解决相关报错

问题原因
  • 核心报错原因是组件销毁后仍在调用setState:你定义的ShowHideCardController是全局单例实例,生命周期和应用生命周期一致,但ShowHideCardState会随着对应Widget的销毁(比如页面退出、组件被移出渲染树)进入defunct不可用状态,由于你没有在组件销毁时移除注册的监听器,后续调用toggleCardVisibility发送通知时,已销毁的State依然会收到回调并触发setState,就抛出了当前错误。
  • 额外存在的逻辑问题:你当前IndexedStack的index取值用的是widget.isFirstCardVisible,而toggle方法修改的是ShowHideCardController的静态变量,二者没有关联,就算没有报错,卡片也不会正常切换显隐。
解决方案

修改状态类代码如下即可解决问题:

class ShowHideCardState extends State<ShowHideCard> {
  @override
  void initState() {
    super.initState();
    showHideCardController.addListener(_updateUI);
  }

  void _updateUI() {
    // 调用setState前先判断组件是否仍挂载,做双重防护
    if (mounted) {
      setState(() {});
    }
  }

  @override
  void dispose() {
    // 组件销毁前移除监听器,避免接收无效通知
    showHideCardController.removeListener(_updateUI);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return IndexedStack(
      // 从controller读取最新的状态值,实现状态同步
      index: ShowHideCardController.isFirstCardVisible ? 0 : 1,
      children: <Widget>[widget.firstCard, widget.secondCard],
    );
  }
}
可选优化建议

建议将isFirstCardVisible改为非静态属性,避免创建多个ShowHideCardController实例时状态互相干扰,修改后控制器代码如下:

class ShowHideCardController extends ChangeNotifier {
  bool isFirstCardVisible = true;

  void toggleCardVisibility() {
    isFirstCardVisible = !isFirstCardVisible;
    notifyListeners();
  }
}

// 全局单例实例
final showHideCardController = ShowHideCardController();

对应build方法里的取值改为`showHideCardController.isFirstCardVisible ? 0 : 1即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:45:03