navigator.pushandremoveuntil is working fine but an exception is thrown: This statement is executed from a class that extends ChangeNotifier (provider).
The following assertion was thrown while finalizing the widget tree: Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
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.
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) {return EmailAuthVC();}), (Route<dynamic> route) => false);
As the error explains, you are trying to use dependOnInheritedWidgetOfExactType
in the dispose method.
What this really means is that the context
you are using is no longer part of the widget tree (because its state as been disposed) and therefore you cannot use it to call dependOnInheritedWidgetOfExactType
.
But where are you using dependOnInheritedWidgetOfExactType
? In Navigator.of(context)
. If you check its source code:
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!;
}
You have to use the context to get the Navigator
before the dispose
method. As explained in the error, you should create a reference to the object (in the didChangeDependencies
method for example) and use it latter.
Here is a concrete example:
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 ...;
}
}
Why not use the initState
method rather than didChangeDependencies
? Because, as much as the context
is not longer valid in dispose
, the context
is not yet valid in initState
because the widget has not yet been inserted in the widget tree.