Flutter调用_onParameterValueChange报错,需在didChangeDependencies中调用指定方法
问题场景
启动页为StatelessWidget,通过ChangeNotifierProvider向MYpage传递信息,MYpage的initState代码如下:
@override void initState() { super.initState(); if (mounted) { setState(() { parameterValueNotifier = widget.parameterValueNotifier; parameterValueNotifier.onValueChanged = _onParameterValueChange; parameterValue = parameterValueNotifier.value; }); } } void _onParameterValueChange(String newValue) { Navigator.of(context).push( MaterialPageRoute( builder: (_) => AnotherPage(parameterValue: newValue), ), ); }
错误日志
I/flutter (25975): Looking up a deactivated widget's ancestor is unsafe.
I/flutter (25975): At this point the state of the widget's element tree is no longer stable.
I/flutter (25975): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
I/flutter (25975): #0 Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4334:9)
解决方案
核心原因
当MYpage已从组件树中移除(deactivated)时,_onParameterValueChange被调用,此时通过当前context获取Navigator会触发错误——因为该context对应的组件状态已失效,无法安全查找祖先组件。
具体修复步骤
- 提前保存Navigator引用
在didChangeDependencies方法中获取并保存NavigatorState的引用,确保后续使用时的安全性:
late NavigatorState _navigator; @override void didChangeDependencies() { super.didChangeDependencies(); _navigator = Navigator.of(context); }
- 替换回调中的导航逻辑
将_onParameterValueChange里的Navigator.of(context)替换为提前保存的_navigator:
void _onParameterValueChange(String newValue) { _navigator.push( MaterialPageRoute( builder: (_) => AnotherPage(parameterValue: newValue), ), ); }
- 清理监听避免内存泄漏
在dispose方法中清空对parameterValueNotifier的回调引用,防止Notifier持有已销毁的State实例:
@override void dispose() { parameterValueNotifier.onValueChanged = null; super.dispose(); }
- 简化initState逻辑
initState中的setState是多余的,直接赋值即可(组件初始化阶段无需触发重建):
@override void initState() { super.initState(); parameterValueNotifier = widget.parameterValueNotifier; parameterValueNotifier.onValueChanged = _onParameterValueChange; parameterValue = parameterValueNotifier.value; }
内容的提问来源于stack exchange,提问作者Artin Yunesi

