Imperative Navigation: Pushing and Popping Screens
Think of app screens as a stack of cards. You `push` a new screen onto the top to show it and `pop` it off to go back. It's ideal for linear flows like list-to-detail. The footgun: popping the last screen closes the app.
WHY IT EXISTS Apps need a structured way to move between different views. Imperative navigation provides a direct, command-based system to manage this screen flow, mirroring how users think about "going to" a new page and "going back". It's the foundational navigation pattern in Flutter.
THE MENTAL MODEL Think of your app's screens as a stack of cards. The Flutter Navigator manages this stack. When you want to show a new screen, you 'push' it onto the top of the stack, covering the previous one. When the user is done, you 'pop' that screen off the top, revealing the one below it. This is a classic Last-In, First-Out (LIFO) data structure.
HOW IT WORKS Flutter's Navigator widget manages a stack of Route objects, which represent your screens. To show a new screen, you call Navigator.push(context, MaterialPageRoute(...)). This adds a new route to the stack. To return, you call Navigator.pop(context), which removes the topmost route. You can also pass data to a new screen through its constructor and receive data back from a popped screen by await-ing the result of the push call.
WHEN TO USE IT Use imperative navigation for simple, linear user flows. It's perfect for master-detail patterns (like a list of emails leading to a single email view), opening a settings page, or stepping through a short wizard. It is the default and most straightforward way to handle navigation in a Flutter app.
WHEN NOT TO USE IT Avoid this pattern for complex, non-linear navigation. If your app requires deep linking (opening a specific screen from a URL), has a complex tab bar interface, or needs to handle browser history in a web app, a declarative routing package like go_router is a much better choice. Managing state across a deep stack of pushed screens can also become very difficult.
ONE CANONICAL EXAMPLE A user is on a product list screen and taps on an item. The app calls Navigator.push() with a route for a ProductDetailScreen, passing the product's ID. The detail screen appears. The user presses the back button (or a custom back arrow), which implicitly calls Navigator.pop(), removing the detail screen from the stack and revealing the product list again.
Read the original → docs.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.