What are Named Routes?
In Flutter, navigation is typically done using Navigator.push with a MaterialPageRoute. For larger apps, this can lead to code that is hard to read and maintain. Named routes allow you to define a map of route names to widgets, then navigate using Navigator.pushNamed. This centralises your route definitions and makes it easier to pass arguments, handle deep linking, and manage app structure.
Defining Named Routes in MaterialApp
You define named routes in the routes property of MaterialApp. It's a Map<String, WidgetBuilder>, where the key is the route name (e.g., '/detail') and the value is a function that returns a widget. The initial route is set with initialRoute.
Now you can navigate using Navigator.pushNamed(context, '/detail').
Passing Arguments with Named Routes
Unlike direct MaterialPageRoute, pushNamed allows you to pass arguments using the arguments parameter. You retrieve them in the destination using ModalRoute.of(context)!.settings.arguments.
Handling Dynamic Routes with onGenerateRoute
For routes that need to accept parameters (e.g., /product/123), you can't use the static routes map. Instead, use onGenerateRoute. This function is called when a named route is pushed but not found in the static routes map. You can parse the route name and return a MaterialPageRoute with the appropriate widget and arguments.
You can also combine routes and onGenerateRoute: static routes go in routes, dynamic ones handled by onGenerateRoute.
Handling Unknown Routes (404)
If a route is not found, you can show a fallback screen using the unknownRoute property. This is useful for handling deep links or user‑typed URLs.
Using named routes with arguments in a typed way
To avoid casting everywhere, you can create a utility class that holds the route names and argument types, or use a package like go_router. For a simple app, you can define a class with constants and a helper method to push with arguments.
Common Mistakes
- Forgetting to include a leading slash: Route names should start with
/(e.g.,/detail).
- Forgetting to include a leading slash: Route names should start with
- Using
pushNamedwithout a corresponding entry: If you don't define the route inroutesoronGenerateRoute, it will throw an error.
- Using
- Not handling arguments: If you push with arguments but don't read them, you'll miss data.
- Ignoring
onGenerateRoutefor dynamic routes: If your app has many dynamic routes, they should be handled inonGenerateRouteto keeproutesclean.
- Ignoring
- Not handling the
unknownRoute: A 404 screen improves UX and prevents crashes.
- Not handling the
Best Practices
- Use constants for route names to avoid typos.
- Keep the route definition map organised – maybe in a separate file.
- For dynamic routes, prefer
onGenerateRouteover a largeroutesmap.
- For dynamic routes, prefer
- Use typed arguments to avoid casting errors – create a custom class or use a package like
go_routerfor complex navigation.
- Use typed arguments to avoid casting errors – create a custom class or use a package like
- Always provide an
unknownRouteto handle deep links gracefully.
- Always provide an
Key Takeaways
- Named routes are defined in
MaterialApp'sroutesmap.
- Named routes are defined in
- Use
Navigator.pushNamedwith an optionalargumentsparameter.
- Use
- Retrieve arguments with
ModalRoute.of(context)!.settings.arguments.
- Retrieve arguments with
- For dynamic routes (e.g.,
/product/123), useonGenerateRoute.
- For dynamic routes (e.g.,
- Handle unknown routes with
unknownRoute.
- Handle unknown routes with
- Centralising routes makes navigation easier to maintain.