user6274128
user6274128

Reputation:

Flutter Navigator.of(context).pop vs Navigator.pop(context) difference

What's the difference between Navigator.of(context).pop and Navigator.pop(context)?

To me both seems to do the same work, what is the actual difference. Is one deprecated?

Upvotes: 46

Views: 52721

Answers (3)

Boris Kayi
Boris Kayi

Reputation: 583

A little bit (not really a little) late to this but the main difference I notice between these two is that Navigator.pop(context) calls Navigator.of(context).pop() with the current widget's BuildContext.

Basically Navigator.of(context).pop() gets a NavigatorState from the passed context and pops the top-most route off the navigator. So when you use it directly, it pops the top-most route off the parent's Navigator (which is the route you are currently on). When you do Navigator.pop(context), you are doing Navigator.of(<current widget's context>).pop() which usually does the same thing since the current widget is usually on the top-most route.

To see differences between objects, you can try to check their hash code. For example with the code below, you can see if the function is being called with the same instance of BuildContext.

final navigatorState = Navigator.of(context);
print(navigatorState.context.hashCode); // Prints the parent's context's hash code.

print(context.hashCode); // Prints the current widget's context's hash code.

BUT this can become tricky when for example you call showDialog on the current context and your widget rebuilds, while the Dialog is still showing. In this case, If you try to pop the dialog with a Navigator.pop(context) you may encounter an Exception such as:

The following assertion was thrown while handling a gesture:
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.

In this use case, using Navigator.of(context).pop() would be better.

Upvotes: 4

conan
conan

Reputation: 536

Navigator.push(context, route) vs Navigator.of(context).push(route)

Navigator is used to manage the app's stack of pages(routes). When push the given route onto the screen(Navigator), We need to get the right Navigator and then push.

Navigator.of(context).push(route) splits .of(context) to get the right Navigator and .push(route). Navigator.of(context) has optional parameters, if rootNavigator is set to true, the NavigatorState from the furthest is given instead.

  static NavigatorState of(
    BuildContext context, {
    bool rootNavigator = false,
    bool nullOk = false,
  })

Navigator.push(context, route) is a static method and do both at the same time. It internally calls Navigator.of(context).push(route). The navigator is most tightly encloses the given context.

static Future<T> push<T extends Object>(BuildContext context, Route<T> route) {
    return Navigator.of(context).push(route);
}

pop() is similar to push().

When multiple Navigators are nested in App. The dialog route created by showDialog(...) method is pushed to the root navigator. If the application has multiple Navigator objects, it may be necessary to call Navigator.of(context, rootNavigator: true).pop(result) to close the dialog rather than just Navigator.pop(context, result).

Upvotes: 36

user6274128
user6274128

Reputation:

There is no difference between the two, source code confirms this. Calling

Navigator.pop(context)

actually calls

Navigator.of(context).pop()

Source code:

static bool pop(BuildContext context, [ dynamic result ]) {
  return Navigator.of(context).pop(result);
}

Upvotes: 31

Related Questions