如何结合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
相关产品推荐
相关产品推荐

