Mus*_*riq 12 navigation navigator dart flutter
navigator.pushandremoveuntil 工作正常,但抛出异常:此语句是从扩展 ChangeNotifier(提供程序)的类执行的。
在完成小部件树时抛出以下断言:查找已停用小部件的祖先是不安全的。
此时小部件的元素树的状态不再稳定。
要在 widget 的 dispose() 方法中安全地引用它的祖先,请通过在 widget 的 didChangeDependency() 方法中调用 dependentOnInheritedWidgetOfExactType() 来保存对祖先的引用。
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) {return EmailAuthVC();}), (Route<dynamic> route) => false);
Run Code Online (Sandbox Code Playgroud)
Lul*_*ntu 40
正如错误所解释的,您正在尝试dependOnInheritedWidgetOfExactType在 dispose 方法中使用。
这真正意味着context您正在使用的不再是小部件树的一部分(因为它的状态已被释放),因此您不能使用它来调用dependOnInheritedWidgetOfExactType.
但你在哪里使用dependOnInheritedWidgetOfExactType?在Navigator.of(context)。如果你检查它的源代码:
static NavigatorState of(
BuildContext context, {
bool rootNavigator = false,
}) {
// Handles the case where the input context is a navigator element.
NavigatorState? navigator;
if (context is StatefulElement && context.state is NavigatorState) {
navigator = context.state as NavigatorState;
}
if (rootNavigator) {
navigator = context.findRootAncestorStateOfType<NavigatorState>() ?? navigator;
} else {
navigator = navigator ?? context.findAncestorStateOfType<NavigatorState>();
}
...
return navigator!;
}
Run Code Online (Sandbox Code Playgroud)
您必须使用上下文来获取方法Navigator 之前的dispose内容。正如错误中所解释的,您应该创建对该对象的引用(didChangeDependencies例如在方法中)并稍后使用它。
这是一个具体的例子:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// The reference to the navigator
late NavigatorState _navigator;
@override
void didChangeDependencies() {
_navigator = Navigator.of(context);
super.didChangeDependencies();
}
@override
void dispose() {
_navigator.pushAndRemoveUntil(..., (route) => ...);
super.dispose();
}
@override
Widget build(BuildContext context) {
return ...;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么不使用该initState方法而不是didChangeDependencies?因为,尽管context中 不再有效dispose,但context中 中 尚未有效initState,因为该小部件尚未插入到小部件树中。
小智 5
就在几个小时前,我也遇到了同样的问题,我得到的错误与您在问题中提到的完全相同。当我试图知道到底出了什么问题时,即使调用一个简单的导航器,我也发现我正在调用一个已经处理的小部件的上下文。确切的情况是,我正在构建一个测验应用程序,当时间结束时,用户将被重定向到结果屏幕。所以我把导航器称为
Future.delayed(Duration(seconds: quiz.quizDuration)).then((value) {
// go to result screen when time is over
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => const ResultScreen()));
});
Run Code Online (Sandbox Code Playgroud)
但如果用户提前回答了所有问题,他也会被重定向到结果屏幕。所以这个小部件已经被释放了,我们的延迟函数将在该时间后完成,并尝试使用已释放小部件的上下文。这就是错误。
我通过检查状态是否持续解决了这个问题。如果小部件仍然存在,则将其处理掉,如果它已经被处理掉,则不执行任何操作。
Future.delayed(Duration(seconds: quiz.quizDuration)).then((value) {
// check if is mounted
if (mounted) {
// if it is mounted then go to result screen, time is off bro..
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => const ResultScreen()));
}
});
Run Code Online (Sandbox Code Playgroud)
这就是我解决问题的方法。所以我想你也可以通过将导航器代码放入其中来解决你的问题
if(mounted)
{
// navigator....
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33022 次 |
| 最近记录: |