Get started in 5 lines
This quickstart guide shows you how to set up NavigationUtils with a minimal working example. You’ll have Navigator 2 working in your app in under 5 minutes.
Install NavigationUtils
Add NavigationUtils to your pubspec.yaml: dependencies :
navigation_utils : ^0.9.11
Then run:
Import the package
Import NavigationUtils in your main file: import 'package:navigation_utils/navigation_utils.dart' ;
Define your routes
Create a list of NavigationData to define your app’s routes: List < NavigationData > routes = [
NavigationData (
label : MyHomePage .name,
url : '/' ,
builder : (context, routeData, globalData) => const MyHomePage (),
),
NavigationData (
label : ProjectPage .name,
url : '/project/:id' ,
builder : (context, routeData, globalData) => ProjectPage (
id : int . tryParse (routeData.pathParameters[ 'id' ] ?? '' ) ?? 0 ,
),
),
];
Each route needs a url because NavigationData maps URLs to pages. The label is optional and enables named routing like Navigator 1.
Initialize NavigationManager
Initialize NavigationManager before running your app: void main () {
NavigationManager . init (
mainRouterDelegate : DefaultRouterDelegate (navigationDataRoutes : routes),
routeInformationParser : DefaultRouteInformationParser (),
);
runApp ( const MyApp ());
}
DefaultRouterDelegate and DefaultRouteInformationParser are convenience classes that handle the Navigator 2 boilerplate for you.
Configure MaterialApp.router
Use MaterialApp.router with NavigationManager’s delegates: class MyApp extends StatelessWidget {
const MyApp ({ super .key});
@override
Widget build ( BuildContext context) {
return MaterialApp . router (
title : 'Navigation Utils Demo' ,
routerDelegate : NavigationManager .instance.routerDelegate,
routeInformationParser : NavigationManager .instance.routeInformationParser,
);
}
}
Navigator 2 uses MaterialApp.router instead of MaterialApp. The routerDelegate and routeInformationParser replace the routes and onGenerateRoute from Navigator 1.
Navigate between pages
With NavigationUtils set up, you can navigate using familiar Navigator 1 methods:
Path-based navigation
Named navigation
Pop navigation
// Navigate using URL paths
NavigationManager .instance. push ( '/project/1' );
Complete example
Here’s the complete minimal example from example/lib/main.dart:
import 'package:flutter/material.dart' ;
import 'package:navigation_utils/navigation_utils.dart' ;
List < NavigationData > routes = [
NavigationData (
label : MyHomePage .name,
url : '/' ,
builder : (context, routeData, globalData) => const MyHomePage (),
),
NavigationData (
label : ProjectPage .name,
url : '/project/:id' ,
builder : (context, routeData, globalData) => ProjectPage (
id : int . tryParse (routeData.pathParameters[ 'id' ] ?? '' ) ?? 0 ,
),
),
];
void main () {
NavigationManager . init (
mainRouterDelegate : DefaultRouterDelegate (navigationDataRoutes : routes),
routeInformationParser : DefaultRouteInformationParser (),
);
runApp ( const MyApp ());
}
class MyApp extends StatelessWidget {
const MyApp ({ super .key});
@override
Widget build ( BuildContext context) {
return MaterialApp . router (
title : 'Navigation Utils Demo' ,
routerDelegate : NavigationManager .instance.routerDelegate,
routeInformationParser : NavigationManager .instance.routeInformationParser,
);
}
}
class MyHomePage extends StatelessWidget {
static const String name = 'home' ;
const MyHomePage ({ super .key});
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : const Text ( 'Home' )),
body : Center (
child : Column (
mainAxisAlignment : MainAxisAlignment .center,
children : [
ElevatedButton (
onPressed : () => NavigationManager .instance. push ( '/project/1' ),
child : const Text ( 'Open Project (Path)' ),
),
ElevatedButton (
onPressed : () => NavigationManager .instance. push (
ProjectPage .name,
pathParameters : { 'id' : '2' },
),
child : const Text ( 'Open Project (Named)' ),
),
],
),
),
);
}
}
class ProjectPage extends StatelessWidget {
static const String name = 'project' ;
final int id;
const ProjectPage ({ super .key, required this .id});
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : Text ( 'Project $ id ' )),
body : Center (
child : Column (
mainAxisAlignment : MainAxisAlignment .center,
children : [
Text ( 'Project Page $ id ' ),
ElevatedButton (
onPressed : () => NavigationManager .instance. pop (),
child : const Text ( 'Back' ),
),
],
),
),
);
}
}
Enable hot reload for routes
When developing, you’ll want hot reload to pick up route changes. Add this to your root widget:
class MyApp extends StatefulWidget {
const MyApp ({ super .key});
@override
State < MyApp > createState () => _MyAppState ();
}
class _MyAppState extends State < MyApp > {
@override
void reassemble () {
NavigationManager .instance.routerDelegate.navigationDataRoutes = routes;
super . reassemble ();
}
@override
Widget build ( BuildContext context) {
return MaterialApp . router (
title : 'Navigation Utils Demo' ,
routerDelegate : NavigationManager .instance.routerDelegate,
routeInformationParser : NavigationManager .instance.routeInformationParser,
);
}
}
Use a getter for routes and avoid final so new instances can be created on hot reload.
Next steps
Now that you have NavigationUtils working, explore these features:
Query parameters Pass data between pages using URL query parameters
Path parameters Capture dynamic URL segments like /user/:userId
Navigation methods Learn about pushReplacement(), popUntil(), set(), and more
Deeplinks Handle deeplinks with authentication and custom logic