// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; void main() => runApp(App()); /// The main app. class App extends StatelessWidget { /// Creates an [App]. App({super.key}); /// The title of the app. static const String title = 'GoRouter Example: Navigator Observer'; @override Widget build(BuildContext context) => MaterialApp.router( routerConfig: _router, title: title, ); final GoRouter _router = GoRouter( observers: [MyNavObserver()], routes: [ GoRoute( // if there's no name, path will be used as name for observers path: '/', builder: (BuildContext context, GoRouterState state) => const Page1Screen(), routes: [ GoRoute( name: 'page2', path: 'page2/:p1', builder: (BuildContext context, GoRouterState state) => const Page2Screen(), routes: [ GoRoute( name: 'page3', path: 'page3', builder: (BuildContext context, GoRouterState state) => const Page3Screen(), ), ], ), ], ), ], ); } /// The Navigator observer. class MyNavObserver extends NavigatorObserver { /// Creates a [MyNavObserver]. MyNavObserver() { log.onRecord.listen((LogRecord e) => debugPrint('$e')); } /// The logged message. final Logger log = Logger('MyNavObserver'); @override void didPush(Route route, Route? previousRoute) => log.info('didPush: ${route.str}, previousRoute= ${previousRoute?.str}'); @override void didPop(Route route, Route? previousRoute) => log.info('didPop: ${route.str}, previousRoute= ${previousRoute?.str}'); @override void didRemove(Route route, Route? previousRoute) => log.info('didRemove: ${route.str}, previousRoute= ${previousRoute?.str}'); @override void didReplace({Route? newRoute, Route? oldRoute}) => log.info('didReplace: new= ${newRoute?.str}, old= ${oldRoute?.str}'); @override void didStartUserGesture( Route route, Route? previousRoute, ) => log.info('didStartUserGesture: ${route.str}, ' 'previousRoute= ${previousRoute?.str}'); @override void didStopUserGesture() => log.info('didStopUserGesture'); } extension on Route { String get str => 'route(${settings.name}: ${settings.arguments})'; } /// The screen of the first page. class Page1Screen extends StatelessWidget { /// Creates a [Page1Screen]. const Page1Screen({super.key}); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: const Text(App.title)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () => context.goNamed( 'page2', pathParameters: {'p1': 'pv1'}, queryParameters: {'q1': 'qv1'}, ), child: const Text('Go to page 2'), ), ], ), ), ); } /// The screen of the second page. class Page2Screen extends StatelessWidget { /// Creates a [Page2Screen]. const Page2Screen({super.key}); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: const Text(App.title)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () => context.goNamed( 'page3', pathParameters: {'p1': 'pv2'}, ), child: const Text('Go to page 3'), ), ], ), ), ); } /// The screen of the third page. class Page3Screen extends StatelessWidget { /// Creates a [Page3Screen]. const Page3Screen({super.key}); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: const Text(App.title)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () => context.go('/'), child: const Text('Go to home page'), ), ], ), ), ); }