Navigator: what it is, screen management in Flutter

Author: IT Sectr Published: 2026-07-02 Reading time: 9 min

Navigator is a navigation manager widget in Flutter that manages a stack of Route objects for moving between screens using push, pop, pushReplacement, and pushNamed methods. Unlike direct widget replacement via State, Navigator works at the level of entire screens: it stores transition history and supports platform-specific animations. According to the Flutter API Reference (2026), Navigator 2.0 (Router) provides declarative navigation management for complex scenarios with deep links and adaptive design. In a typical application, Navigator ensures correct behavior of the Back button on Android and swipe gestures on iOS.

Key Takeaways

  • Navigator — a navigation manager that controls a stack of routes via push, pop, pushNamed, pushReplacement, and pushAndRemoveUntil methods
  • Route stack — Navigator stores screens in a LIFO stack: each push adds a screen on top, pop removes the topmost
  • pushNamed — navigation by named routes defined in MaterialApp.routes or onGenerateRoute
  • pushReplacement — replaces the current screen with a new one without the ability to go back (e.g., after login)
  • Navigator 2.0 — declarative API with Router, RouterDelegate, and RouteInformationParser for web and desktop navigation

What is Navigator in Flutter

Navigator is a widget that manages a stack of Route objects, implementing screen navigation in a Flutter application. Each call to push places a new Route on top of the stack, pop removes the top Route and returns to the previous screen. MaterialApp automatically creates a Navigator for the entire application, making it accessible via Navigator.of(context).

Unlike StatefulWidget, where content replacement happens via setState inside a single widget, Navigator operates with entire screens that have their own lifecycle. Each Route in the stack is an isolated state with its own BuildContext, preventing memory leaks and simplifying dependency management. When pop is called, the unused Route is destroyed, freeing resources.

According to the Flutter Navigation Guide (2026), Navigator has evolved from an imperative API (Navigator 1.0) to a declarative one (Navigator 2.0). Navigator 1.0 uses push/pop methods directly, which is convenient for simple scenarios. Navigator 2.0 (Router) is suitable for applications with deep links, adaptive navigation, and web routing.

How Navigator works under the hood

Internally, Navigator uses Overlay — a special widget that displays Routes one on top of another. Each Route creates its own position in the Overlay with a z-index corresponding to its depth in the stack. This explains why when push is called, the new screen animates on top of the previous one, and when pop is called, the previous screen is already ready to display: it was not destroyed but remained in the Overlay below the new one.

For transition animations, Navigator uses PageTransitionsTheme, which can be overridden in ThemeData. Platform-specific animations are set via CupertinoPageRoute for iOS (slide from right) and MaterialPageRoute for Android (slide from bottom). Navigator automatically selects the correct animation when using PlatformRoute.

Navigator provides a set of methods for managing the Route stack. Each method solves a specific navigation task — from a simple transition to a complete replacement of the screen history. Let us review the main methods with usage examples.

MethodDescriptionUse Case
pushAdds a Route to the top of the stackNavigate to a new screen with the ability to return
popRemoves the top Route from the stackReturn to the previous screen
pushReplacementReplaces the current Route with a new oneAfter login — the login screen is replaced by the main screen
pushAndRemoveUntilAdds a Route and removes previous ones until a condition is metNavigate to the main screen with history clearance
popUntilRemoves Routes from the stack until a condition is metReturn to a specific screen in the history
maybePopCalls pop only if the stack contains >1 RoutePrevent app closure on accidental back press

Push and Pop: Basic Operations

The push method takes a Route and returns a Future with the result passed during pop. This allows receiving data from the screen that was navigated to. For example, a date picker screen can return a DateTime via Navigator.pop(context, selectedDate). The pop method without arguments returns null, with an argument — passes the value to the calling screen.

PushReplacement: Replacing a Screen

pushReplacement replaces the current Route with a new one, removing the current route from the stack. This is critical for scenarios where the user should not be able to return to the previous screen. A typical example is the login screen: after successful login, the current screen is replaced by the main screen, and the Back button does not return to the login form.

Named Routes and onGenerateRoute

Navigator supports navigation by named routes via the pushNamed method. Instead of creating a Route directly, the developer specifies a string identifier, and Navigator automatically creates the Route based on the configuration in MaterialApp. This simplifies code and centralizes route definition in one place.

Named routes are defined through the routes property in MaterialApp, where each key is a path string and the value is a function returning a Widget. For dynamic routes (with parameters), onGenerateRoute is used — a callback that receives RouteSettings and returns a Route. This allows passing arguments via the arguments parameter and implementing deep navigation.

According to the Flutter Cookbook (2026), passing arguments via pushNamed is done using the arguments: Object? parameter. The receiving screen extracts arguments via ModalRoute.of(context)!.settings.arguments, providing type-safe data transfer without global variables or InheritedWidget.

Handling Unknown Routes

The onUnknownRoute property in MaterialApp handles cases where pushNamed is called with a non-existent route. This is useful for showing a 404 screen or redirecting to the home page. In combination with onGenerateRoute, it ensures full coverage of all possible navigation scenarios.

Navigator 2.0 (also known as the Router API) is a declarative approach to navigation introduced in Flutter 2.0. Unlike the imperative Navigator 1.0, where the developer calls push/pop, Router manages navigation through state, automatically synchronizing the browser URL with the current screen. This is especially important for web applications and desktop versions.

The Navigator 2.0 architecture consists of three key components: RouteInformationParser parses the URL into a route configuration, RouterDelegate transforms the configuration into a list of Routes, and BackButtonDispatcher handles the system Back button. This architecture makes navigation fully predictable and testable.

To simplify working with Navigator 2.0, there are wrapper packages: go_router (recommended by Google), auto_route, and beamer. go_router provides a declarative DSL for defining routes with support for nested navigation, redirects, and deep links without manually implementing RouterDelegate. According to pub.dev (2026), go_router is used in 35% of new Flutter projects that prefer a declarative approach.

Consider an example of Navigator with named routes and data passing between screens. The code demonstrates a product list screen, a transition to a detail screen, and returning with a result.

dart
// Route configuration in MaterialApp
MaterialApp(
  initialRoute: '/',
  onGenerateRoute: (RouteSettings settings) {
    if (settings.name == '/') {
      return MaterialPageRoute(
        builder: (context) => const ProductListPage(),
      );
    }
    if (settings.name == '/product') {
      final productId = settings.arguments as String;
      return MaterialPageRoute(
        builder: (context) => ProductDetailPage(productId: productId),
      );
    }
    return MaterialPageRoute(
      builder: (context) => const NotFoundPage(),
    );
  },
)

// Navigation with data passing
final result = await Navigator.pushNamed(
  context,
  '/product',
  arguments: 'product_42',
);

// Getting data on the receiving screen
final args = ModalRoute.of(context)!.settings.arguments as String;

// Replace screen after login
Navigator.pushReplacementNamed(context, '/home');

// Clear stack to main screen
Navigator.pushNamedAndRemoveUntil(
  context,
  '/home',
  (route) => false,
);

In the example, Navigator.pushNamed passes the product ID to the detail screen. Upon return via Navigator.pop(context, updatedProduct), the calling screen receives the updated data in the result variable. pushReplacementNamed replaces the current screen after authorization, and pushNamedAndRemoveUntil with the condition (route) => false completely clears the stack, preventing navigation back to previous screens.

Frequently Asked Questions

What is the difference between Navigator 1.0 and Navigator 2.0?

Navigator 1.0 — an imperative API with push and pop methods, convenient for simple mobile applications. Navigator 2.0 — a declarative API via Router, RouterDelegate, and RouteInformationParser, necessary for web applications with URL routing, deep links, and adaptive navigation. For practical projects, go_router is recommended as a simplified wrapper over Navigator 2.0.

How to pass data between screens via Navigator?

Data is passed via the arguments parameter in pushNamed or directly through the Route constructor. On the receiving screen, data is retrieved via ModalRoute.of(context)!.settings.arguments. To return data, use Navigator.pop(context, result) — the calling screen will receive the result as a Future value returned from push.

Why does the Back button not return to the previous screen?

This happens if the current screen was opened via pushReplacement, which removes the previous Route from the stack. In this case, there is no navigation history, and the Back button closes the application. To return, use regular push instead of pushReplacement. Also check that the Navigator.pop call is correctly handled on the current screen.

How to prevent returning to the previous screen?

Use pushReplacement to replace the current screen with a new one — the previous screen is removed from the stack and cannot be returned to. For complete history clearance, use pushAndRemoveUntil with the condition (route) => false. Alternatively, you can override WillPopScope (deprecated) or PopScope to intercept the system Back button.

What is go_router and when to use it?

go_router is a declarative navigation package from Google built on top of Navigator 2.0. It provides a simple DSL for defining routes with support for nesting, redirects, deep links, and ShellRoute for BottomNavigationBar. Use go_router for new projects, especially if web support or complex navigation patterns with guarded routes are required.

Summary

  • Navigator — Flutter navigation manager controlling the Route stack with push, pop, pushReplacement, and pushAndRemoveUntil methods
  • LIFO stack — each push adds a Route on top, pop removes the topmost; the stack stores transition history on a last-in-first-out basis
  • pushReplacement — replaces the current screen without the ability to return, critical for login and onboarding scenarios
  • Named routes — pushNamed with RouteSettings and onGenerateRoute for centralized route definition with argument passing
  • Navigator 2.0 — declarative navigation via Router, RouterDelegate, and RouteInformationParser for web deep links
  • go_router — Google-recommended wrapper over Navigator 2.0 with a simple DSL and ShellRoute support
  • Data passing — via arguments in pushNamed and result return through Future from push using Navigator.pop(context, value)

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also