Skip to main content

Using Named Routes

1. Defining Named Routes

Property Description Example
name Name of the route 'home'
builder Function that builds the widget for this route (context) => HomeScreen()

Example: Defining a Named Route

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/profile': (context) => ProfileScreen(),
      },
    ),
  );
}

2. Navigating with Named Routes

Property Description Example
onGenerateRoute Callback to generate routes dynamically onGenerateRoute: (settings) { ... }
onUnknownRoute Handler for undefined routes onUnknownRoute: (settings) { ... }

Example: Defining Named Routes

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/profile': (context) => ProfileScreen(),
        '/settings': (context) => SettingsScreen(),
      },
    );
  }
}

Example: Navigating to a Named Route

onPressed: () {
  Navigator.pushNamed(context, '/profile');
}

Example: Passing Arguments to Named Routes

Navigator.pushNamed(
  context,
  '/user',
  arguments: {'id': '123', 'name': 'John'},
);
Note: Named routes must be defined in the routes map of MaterialApp or WidgetsApp.
Warning: Using Navigator.pushNamed without defining the route will throw an exception.

3. Using onGenerateRoute Callback

Property Description Usage
onGenerateRoute Callback function to handle route generation for named routes not defined in routes
onGenerateRoute: (RouteSettings settings) {
  // Handle route generation dynamically
}

Example: onGenerateRoute Implementation

MaterialApp(
  onGenerateRoute: (RouteSettings settings) {
    if (settings.name == '/user') {
      return MaterialPageRoute(
        builder: (context) => UserScreen(),
        settings: settings,
      );
    }
    return null; // Route not found
  },
)
Note: onGenerateRoute is called when a route is not found in the routes map.

Key Points

  • onGenerateRoute is used for dynamic route generation.
  • It's called when a named route is not found in the routes map.
  • Returns a Route object or null if route is not handled.

4. Using onUnknownRoute Callback

Property Description Usage
onUnknownRoute Callback invoked when a route is not found in the route table. onUnknownRoute: (RouteSettings settings) { ... }

Example: Handling Unknown Routes

MaterialApp(
  onUnknownRoute: (RouteSettings settings) {
    return MaterialPageRoute(
      builder: (context) => Scaffold(
        appBar: AppBar(title: Text('Route Not Found')),
        body: Center(child: Text('The route \${settings.name} was not found.')),
      ),
    );
  },
)
Note: The onUnknownRoute is useful for displaying a custom 404 page or redirecting to a default route when a user navigates to an invalid route.

5. Passing Arguments to Named Routes

Argument Type Description Usage
arguments Passes a single argument to the route Navigator.pushNamed(context, '/route', arguments: {'key': 'value'});
arguments Passes multiple arguments to the route Navigator.pushNamed(context, '/route', arguments: {'name': 'John', 'age': 30});

Example: Accessing Arguments in Route

class MyRoutePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
    return Scaffold(
      appBar: AppBar(title: Text('Arguments Page')),
      body: Center(
        child: Text('Name: ${args['name']}, Age: ${args['age']}'),
      ),
    );
  }
}

6. Extracting Route Arguments

Property Description Example
ModalRoute.of(context) Retrieves the current route from the navigation stack
final route = ModalRoute.of(context);
final String? id = route?.settings.arguments['id'];
settings.arguments Arguments passed to the route during navigation
Navigator.pushNamed(
  context,
  '/user',
  arguments: {'id': '123', 'name': 'John'},
);

Example: Extracting Route Arguments

class UserScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final route = ModalRoute.of(context);
    final String? id = route?.settings.arguments['id'];
    return Scaffold(
      appBar: AppBar(title: Text('User $id')),
      body: Center(child: Text('User ID: $id')),
    );
  }
}

7. Using RouteSettings Class

Property Description Example
name The route name (optional) '/user/profile'
arguments Arguments passed to the route (optional) {'userId': '123'}
isInitialRoute Indicates if this is the initial route (read-only) false

Example: Creating a Route with RouteSettings

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/user/profile': (context) => UserProfileScreen(),
      },
      onGenerateRoute: (settings) {
        if (settings.name == '/user/profile') {
          return MaterialPageRoute(
            builder: (context) => UserProfileScreen(),
            settings: RouteSettings(
              name: '/user/profile',
              arguments: {'userId': '123'},
            ),
          );
        }
        return null;
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(
              context,
              '/user/profile',
              arguments: {'userId': '123'},
            );
          },
          child: Text('Go to Profile'),
        ),
      ),
    );
  }
}

class UserProfileScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map?;
    return Scaffold(
      appBar: AppBar(title: Text('User Profile')),
      body: Center(
        child: Text('User ID: ${args?['userId']}'),
      ),
    );
  }
}

8. Creating Route Observers

Route observers allow you to monitor route changes and lifecycle events in your Flutter app. They are useful for logging, analytics, or performing actions when specific routes are pushed or popped.

Property Description Usage
didPush Called when a new route is pushed onto the stack. void didPush(Route route, Route previousRoute)
didPop Called when a route is popped from the stack. void didPop(Route route, Route previousRoute)
didRemove Called when a route is removed from the stack. void didRemove(Route route, Route previousRoute)
didPushNext Called when a new route is pushed on top of the current route. void didPushNext(Route route, Route previousRoute)
didPopNext Called when the current route is popped and replaced with another. void didPopNext(Route route, Route previousRoute)

Example: Implementing Route Observer

class MyRouteObserver extends RouteObserver<PageRoute> {
  @override
  void didPush(Route route, Route previousRoute) {
    print('New route pushed: ${route.settings.name}');
  }

  @override
  void didPop(Route route, Route previousRoute) {
    print('Route popped: ${route.settings.name}');
  }
}

Example: Using Route Observer in App

void main() {
  runApp(
    MaterialApp(
      navigatorObservers: [MyRouteObserver()],
      home: HomeScreen(),
    ),
  );
}

9. Implementing Route Guards

Route guards in Flutter are used to control access to routes based on conditions such as authentication status, user permissions, or other business logic. They help in preventing unauthorized navigation to specific screens.

Guard Type Description Implementation
Navigation Guard Prevents navigation to a route based on conditions.
onGenerateRoute: (settings) {
  if (settings.name == '/protected') {
    if (!isAuthenticated) {
      return MaterialPageRoute(builder: (context) => LoginScreen());
    }
  }
  return null;
}
Redirect Guard Redirects to another route if the current route is not accessible.
onGenerateRoute: (settings) {
  if (settings.name == '/admin') {
    if (!isAdmin) {
      return MaterialPageRoute(builder: (context) => HomeScreen());
    }
  }
  return null;
}

Example: Navigation Guard Implementation

class AuthGuard {
  static Route<Object>? onGenerateRoute(RouteSettings settings) {
    if (settings.name == '/dashboard') {
      if (!isAuthenticated) {
        return MaterialPageRoute(
          builder: (context) => LoginScreen(),
        );
      }
    }
    return null;
  }
}
Note: Route guards are typically implemented using onGenerateRoute in the MaterialApp or WidgetsApp widget.
Warning: Ensure that all guards are properly handled to avoid infinite loops or unexpected behavior during navigation.

10. Using initialRoute Property

Property Description Usage
initialRoute Specifies the route to navigate to when the app starts. initialRoute: '/home'

Example: Setting initialRoute in MaterialApp

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/home',
      routes: {
        '/home': (context) => HomeScreen(),
        '/profile': (context) => ProfileScreen(),
      },
    );
  }
}

Was this article helpful?