auto_route 0.4.2

  • Readme
  • Changelog
  • Example
  • Installing
  • 97

auto_route: #

AutoRoute is a route generation library, where everything needed for navigation is automatically generated for you.

Installation #

  # add auto_route to your dependencies
  auto_route: [latest-version]

  # add the generator to your dev_dependencies
  auto_route_generator: [latest-version]
  # of course build_runner is needed to run the generator

Setup and Usage #

First create a router config class then annotate it with @MaterialAutoRouter, @CupertinoAutoRoute or @CustomAutoRoute. It's name must be prefixed with $ to get a generated class with the same name minus the $.
$Router => Router

Note: using $ prefix is mandatory.
@MaterialAutoRouter(...config)  //CustomAutoRoute(..config)
class $Router {


Now start adding your routes as class fields with the desired route names:

Only use the @MaterialRoute() or @CupertinoRoute() annotations to customize your route

class $Router {
 // use @initial or @CupertinoRoute(initial: true) to annotate your initial route.
  HomeScreen homeScreenRoute; // your desired route name

  SecondScreen secondScreenRoute;

  //optional route Customization
  @CupertinoRoute(fullscreenDialog: true)
  LoginScreen loginScreenRoute;

Next simply Run the generator

Use the [watch] flag to watch the files system for edits and rebuild as necessary.

flutter packages pub run build_runner watch

if you want the generator to run one time and exits use

flutter packages pub run build_runner build

Finalize the Setup

after you run the generator your router class will be generated containing all of your route names and the onGenerateRoute function implementation.

class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
    // Tell MaterialApp to use our ExtendedNavigator instead of
    // the native one by assigning it to it's builder
    // instead of return the nativeNavigator we're returning our ExtendedNavigator
     builder: ExtendedNavigator<Router>(router: Router()),
     // this's a shorthand for
     builder: (ctx, nativeNavigator) => ExtendedNavigator<Router>(router: Router())

Inside of the Generated file

// a Routes class that holds all of your static route names
abstract class Routes {
  static const homeScreen = '/';
  static const secondScreen = '/second-screen';
// the onGenerateRoute function implementation
class Router extends RouterBase{
      Route<dynamic> onGenerateRoute(RouteSettings settings) {
        switch ( {
        // The generated code for LoginScreen is
          case Routes.loginScreenRoute:
            return CupertinoPageRoute<dynamic>(
              builder: (_) => LoginScreen(),
              settings: settings,
              fullscreenDialog: true

          // autoRoute handles unknown routes for you
            return unknownRoutePage(;
 } }

 // Argument holder classes if exist ...

You can either use context to look up your Navigator in your widgets tree or without context, using ExtendedNavigator.ofRouter

// with context
// without context
// or if you're working with only one navigator

to generate extension methods set the generateNavigationHelperExtension property inside of MaterialAutoRouter() to true

This will generate

extension RouterNavigationHelperMethods on ExtendedNavigatorState {
  Future pushHomeScreen() => pushNamed(Routes.homeScreen);
  Future<bool> pushSecondScreen(
          {@required String title, String message}) =>
          arguments: SecondScreenArguments(title: title, message: message));

Then use it like follows


Customization #

MaterialAutoRouter | CupertinoAutoRouter
PropertyDefault valueDefinition
generateRouteList [bool]falseif true a list of all routes will be generated
generateNavigationHelperExtension [bool]falseif true an Navigator extenstion will be generated with helper push methods of all routes


PropertyDefault valueDefinition
transitionsBuilder [Function]nullextension for the transitionsBuilder property in PageRouteBuilder
opaque [bool]trueextension for the opaque property in PageRouteBuilder
barrierDismissible [bool]falseextension for the barrierDismissible property in PageRouteBuilder
durationInMilliseconds [double]nullextension for the transitionDuration(millieSeconds) property in PageRouteBuilder

MaterialRoute | CupertinoRoute | CustomRoute

PropertyDefault valueDefinition
initial [bool]falsemark the route as initial '\'
name [String]nullthis will be assigned to the route variable name if provided (String homeScreen = [name]);
fullscreenDialog [bool]falseextension for the fullscreenDialog property in PageRoute
maintainState [bool]trueextension for the maintainState property in PageRoute

CupertinoRoute Specific => CupertinoPageRoute

PropertyDefault valueDefinition
title [String]nullextension for the title property in CupertinoPageRoute

CustomRoute Specific => PageRouteBuilder

PropertyDefault valueDefinition
transitionsBuilder [Function]nullextension for the transitionsBuilder property in PageRouteBuilder
opaque [bool]trueextension for the opaque property in PageRouteBuilder
barrierDismissible [bool]falseextension for the barrierDismissible property in PageRouteBuilder
durationInMilliseconds [double]nullextension for the transitionDuration(millieSeconds) property in PageRouteBuilder


Marks route as a custome route-not-found page. There can be only one unknown route per Router.

Passing Arguments to Routes #

That's the fun part!

You don't actually need to do anything extra. AutoRoute automatically detects your route parameters and handles them for you, and because Types are important it will make sure you pass the right argument Type

class ProductDetails extends StatelessWidget {
  final int productId;
// your route parameters are handled based on
// your widget route constructor
  const ProductDetails(this.productId);
  Widget build(BuildContext context)...

Generated code for the above example

 final args = settings.arguments;
  case Routes.productDetailsRoute:
   // ProductDetails screen is expecting a productId of type <int>
   // so we check the passed arguments against it
    if (hasInvalidArgs<int>(args))
    // if the passed in args are mistyped, an error route page will be displayed instead
    return misTypedArgsRoute<int>(args);
    // otherwise we navigate to the desired screen
    final typedArgs = args as int;
    return MaterialPageRoute(
      builder: (_) => ProductDetails(typedArgs),
      settings: settings,

Passing multiple arguments (Don't worry, We're not using a dynamic Map!)

Since you can only pass one argument to the Navigator, if you define more then one parameter in your screen constructor autoRoute will automatically generate a class that holds your screen arguments and keep them typed.

class WelcomeScreen extends StatelessWidget {
  final String title;
  final String message;
  const WelcomeScreen({this.title = "Default Title",@required this.message});

  Widget build(BuildContext context)...

Generated code for the above example

  • Default values are respected.
  • Required fields are also respected and handled properly.
//WelcomeScreen arguments holder class is generated
class WelcomeScreenArguments {
  final String title;
  final String message;
  // you're not going to lose your default values;
  WelcomeScreenArguments({this.title = "Default Title",@required this.message});

 case Routes.welcomeScreenRoute:
      // if your class holder contains at least one required field the whole argument class is considered required and can not be null
        if (hasInvalidArgs<WelcomeScreenArguments>(args,isRequired: true))
          return misTypedArgsRoute<WelcomeScreenArguments>(args);
        final typedArgs =
            args as WelcomeScreenArguments ?? WelcomeScreenArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) =>
              WelcomeScreen(title: typedArgs.title, message: typedArgs.message),
          settings: settings,
Pass your typed args using the generated arguments holder class
    arguments: WelcomeScreenArguments(
        title: "Hello World!"
        message: "Let's AutoRoute!"

Nested Navigators #

Create your nested router class and define your routes as before.

class $MyNestedRouter {
  NestedHomePage nestedHomePage;
  NestedSecondPage nestedSecondPage;
Hook up your nested navigator with the Generated Router class
 ExtendedNavigator<MyNestedRouter>(router: MyNestedRouter()),

And That's that! Now use your nested router's navigator to navigate within your nested navigator as follows

// inside of widgets below your nested ExtendedNavigator()
// or without context

Route guards #

Implementing route guards requires a little bit of setup:

  1. Create your route guard by extending RouteGuard from the autoRoute package
class AuthGuard extends RouteGuard {
 Future<bool> canNavigate(
     ExtendedNavigatorState navigator, String routeName, Object arguments) async {

   SharedPreferences prefs = await SharedPreferences.getInstance();
   return prefs.getString('token_key') != null;
  1. Register your guards pass your guards to the guards property inside of ExtendedNavigator
class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: ExtendedNavigator<Router>(
        router: Router(),
        guards: [AuthGuard()],
  1. Annotated the routes you want to guard with @GuardedBy([..guards]) and pass in your guards as types.
 ProfileScreen profileScreen;

Handling Wrapped Routes #

To wrap your route with a parent widget like a Provider or such, simply implement AutoRouteWrapper, and let wrappedRoute accessor return (this) as the child of your wrapper widget.

class ProductsScreen extends StatelessWidget implements AutoRouteWrapper {
  Widget get wrappedRoute => Provider(create: (ctx) => ProductsBloc(), child: this);

Custom Route Transitions #

To use custom Transitions use the @CustomRoute() annotation and pass in your preferences.
The TransitionsBuilder function needs to be passed as a static/const reference that has the same signature as the TransitionsBuilder Function of the PageRouteBuilder class.
The included TransitionsBuilders Class contains a preset of common Transitions builders

@CustomRoute(transitionsBuilder: TransitionBuilders.slideBottom,durationInMilliseconds: 400)
LoginScreen loginScreenRoute;

Use @CustomAutoRouter() to define global custom route Transitions.

You can of course use your own transitionsBuilder function as long as it has the same function signature.
The function has to take in exactly a BuildContext, Animation[Double], Animation[Double] and a child Widget and it needs to return a Widget, typically you would wrap your child with one of flutter's transition Widgets as follows.

Widget zoomInTransition(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
 // you get an animation object and a widget
 // make your own transition
    return ScaleTransition(scale: animation, child: child);

Now pass the reference of your function to @CustomRoute() annotation.

@CustomRoute(transitionsBuilder: zoomInTransition)
ZoomInScreen zoomInScreenRoute {}

Resources #

Acknowledgements #

Thanks to Peter Leibiger for his valuable advice.

Problems with the generation? #

Make sure you always Save your files before running the generator, if that doesn't work you can always try to clean and rebuild.

flutter packages pub run build_runner clean

ChangeLog #

[0.4.2] Breaking Changes #

  • Fix Android soft back button always exists App

[0.4.1] Breaking Changes #

  • Fix isInitialRoute not defined for RouteSettings in flutter 1.15.+

[0.4.0] Breaking Changes #

  • Change using ExtendedNavigator instead of the native Navigator
  • Fix initial route does not go through guards
  • Change generated router class is no longer static
  • Change routes are generated in their own class now "Routers"
  • Add option to generate navigation helper methods extension
  • Update README file

[0.3.1] #

  • Fix Compilation Fails in flutter 1.15.+
  • Fix third party imports src instead of library
  • Fix guardedRoutes is generated even if it's empty
  • Add support for custom unknown route screen

[0.3.0] Breaking Changes! #

  • Add global route customization Use MaterialAutoRouter, CupertinoAutoRouter or CustomAutoRouter instead of AutoRouter
  • Navigator key is now accessed by calling Router.navigator.key instead of Router.navigatorKey.
  • Add Route guards
  • Add optional returnType param in all AutoRoute types.
  • Remove generate Navigator Key optional.
  • Fix generate error when using dynamic vars in route widget constructors

[0.2.2] #

  • Add option to generate a list with all route names
  • change generating navigator key is now optional
  • Fix prevent importing system library files
  • Change generated route path name are now Kabab cased (url-friendly)
  • Add ability to use custom path names in all route types
  • Update README file

[0.2.1] #

  • add Route Wrapper
  • add initial flag as a property in all route types
  • change prefix const route names with class name.
  • add fullscreenDialog property to @CustomRoute()

[0.2.0+1] #

  • format README file

[0.2.0] #

Breaking Changes! #

  • change to using a single config file instead of annotating the actual widget class due to performance issues.
  • add @MaterialRoute(), @CupertinoRoute() and @CustomRoute() annotations
  • remove @AutoRoute() annotation and add @AutoRouter()
  • handle required parameters.
  • add navigating with a global navigator key [without context].
  • support nested navigators.

[0.1.1] #

  • code formatting.

[0.1.0] #

  • initial release.


class HomeScreen extends StatelessWidget{}

class LoginScreen extends StatelessWidget {}

class $Router{
 HomeScreen homeScreenRoute;
 LoginScreen loginScreenRoute;

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  auto_route: ^0.4.2

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:auto_route/auto_route.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Mar 27, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.5.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8