37

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?

3 Answers3

27

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).

conan
  • 428
  • 5
  • 11
23

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);
}
  • 3
    there is no difference: https://www.crossdart.info/p/flutter/0.0.38-dev/src/widgets/navigator.dart.html#line-594 – pskink Apr 06 '19 at 11:02
  • @pskink Very interesting, he showed a working code with the difference but source code denies. – CopsOnRoad Apr 06 '19 at 11:18
  • @CopsOnRoad actually i did not run his code: i believe in my eyes (or maybe there is something i dont understand in that simple one line of code i linked above...) – pskink Apr 06 '19 at 11:24
  • @pskink Even I didn't run that, I also thought there would be no difference but if OP mentioned that that means there would be some. – CopsOnRoad Apr 06 '19 at 11:25
  • 2
    You didn't call your pop method in the first example. `Navigator.of(context).pop` should be `Navigator.of(context).pop()`. That might be the issue. – nonybrighto Apr 06 '19 at 13:44
4

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.

Boris Kayi
  • 486
  • 7
  • 13