Navigator is used to navigate between the pages and sometimes we want to subscribe for flutter Navigator/Router Events to update the widget state or to perform the specific task during the push and pop of page. Flutter provider RouteObserver mixin to subscribe the events of navigator by which we can perform our task on push and pop.
RouteAware is an interface for objects that know about their present in route. let’s understand with example
Step 1 : Create flutter project
Very first step is to create the fluter application using command line tool or in Android studio.
flutter create example_app
This will create a new project with name my_app then go in to the folder.
Step 2 : Create a class and Add RouteObserver
Create a simple class named as Helper so that we can use it across multiple files
import 'package:flutter/material.dart';
class Helper {
static final RouteObserver<PageRoute> _routeObserver = RouteObserver();
}
Step 3 : Create two widgets for navigation
Now, Create two widgets to navigate between the pages. Let’s create one widget name as Home
Page and Second as Products
. From home screen we will pass params to it and will access it to another page which is Products.
File : lib/Home
Page.dart
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with RouteAware {
@override
void didPush() {
print('HomePage: Called didPush');
super.didPush();
}
@override
void didPop() {
print('HomePage: Called didPop');
super.didPop();
}
@override
void didPopNext() {
print('HomePage: Called didPopNext');
super.didPopNext();
}
@override
void didPushNext() {
print('HomePage: Called didPushNext');
super.didPushNext();
}
@override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
Helper.routeObserver.subscribe(this, ModalRoute.of(context)!);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Home Screen"),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/Products',
arguments: {"id": 1, "name": "apple"});
},
child: const Text("Navigate to Apple")),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/Products',
arguments: {"id": 2, "name": "Nokia"});
},
child: const Text("Navigate to Nokia"))
],
),
),
);
}
}
Here we used Navigator.push
to navigate to another page which is Products
and also used Scaffold for material mobile design. As you can see we used arguments
to pass the params to another page.
we added
@override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
Helper.routeObserver.subscribe(this, ModalRoute.of(context)!);
});
super.initState();
}
and methods
- didPop(): Called when we call pop method of navigator.
- didPopNext(): In this method, on the off chance that you have extended HomePage with RouteAware, and in case SecondPage is popped so HomePage is noticeable now, didPopNext is called.
- didPush(): called when the current screen or route has been pushed into the navigation stack.
- didPushNext(): called when a new screen/route is pushed from the current screen and the current screen is no longer visible.
and lib/
.dartProducts
class Products extends StatelessWidget {
const Products({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
Map arguments = ModalRoute.of(context)?.settings.arguments as Map;
return Scaffold(
appBar: AppBar(
title: Text('Product ${arguments['name']}'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("${arguments['name']} and id ${arguments['id']}"),
ElevatedButton(onPressed: (){
Navigator.pop(context);
}, child: const Text("Navigate back"))
],
),
),
);
}
}
We used here Navigator.pop
to go back to the last page.
Step 3 : Add Routing widget
Now create routing for these two pages using MaterialApp
. As you can see in below example we have created two routes /
to access the home screen and /Products
to access the products page.
We also create builder using Navigator.
class AppRouter extends StatelessWidget {
const AppRouter({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Named Routes Demo',
navigatorObservers: [Helper.routeObserver],
initialRoute: '/',
routes: {
'/': (context) => const HomePage(),
'/Products': (context) => const Products(),
});
}
}
Here we added navigatorObservers: [Helper.routeObserver]
for subscribe the events of navigator in widget.
Step 4 : Add Page to main file
Simply run the project using command line or in android studio to check the implementation.
import 'package:flutter/material.dart';
import 'package:example_app/AppRouter.dart';
import 'package:example_app/HomePage.dart';
import 'package:example_app/Products.dart';
void main() {
runApp(const AppRouter());
}
Check the implementation here and you can check the console for logs