• What is route_generator
  • features
  • Rely on
  • The generated code
  • route_annotation
  • Code sample
    • Define routing App
    • Defining the routing page
    • Define routing page parameters
  • Custom route (Priority: 3)
  • Custom route (Priority: 2)
  • Custom route (Priority: 1)
  • The routing code is automatically generated from the dependency packages in the pubspec.yaml file
  • Questions about build_Runner Watch mode
  • Matters needing attention
  • Final generated code
  • Q&A
  • Example

Repository

What is route_generator

This is a simple library for generating Flutter routes. It requires only a small amount of code. Then annotations are combined with source code generation to automatically generate routing tables, eliminating the need to manually manage the routing code.

features

  • User-defined route name
  • Custom route animation
  • Customize route parameters
  • Custom routing logic
  • Support automatic generation of routing codes from dependent packages in pubspec.yaml files

Rely on

dependencies:
  # Your other regular dependencies here
  route_annotation: ^ 0.2.0

dev_dependencies:
  # Your other dev_dependencies here
  build_runner: ^ 1.5.0
  route_generator: ^ 0.1.4
Copy the code

The generated code

  • A single building

    Run the flutter pub run build_runner build in the project root directory to generate routing code for the project if needed. This triggers a one-time build that traverses the source files, selects the relevant files, and generates the necessary routing code for them. While this is convenient, if you don’t have to build manually every time you make a change in a model class, you can choose to build continuously.

  • Continue to build

    Start watcher by running flutter pub run build_runner watch in the project root directory to make our source code generation process much easier. It monitors changes in the project files and automatically builds the necessary files as needed.

route_annotation

annotation description
Router This annotation identifies a class that is a Flutter App and generates the corresponding routing code
RoutePage This annotation is used to annotate a routing page
RouteParameter An annotation to mark page parameters, designed for optional parameters only. Used forRoutePage
RouteField This annotation is used to mark a fully custom route. The annotated object must be a static field of the route page class
PageRouteBuilderFuntcion This annotation identifies a routing pageRouteFactoryA static method
RoutePageBuilderFunction This annotation identifies a routing pageRoutePageBuilderA static method
RouteTransitionBuilderFunction This annotation identifies a routing pageTransitionBuilderA static method
RouteTransitionDurationField This annotation identifies the transition duration of a custom routing page
router new withRouter()The same
page new withRoutePage()The same
initialPage new withRoutePage(isInitialRoute: true)The same
routeField new withRouteField()The same
routeBuilder new withPageRouteBuilderFuntcion()The same
pageBuilder new withRoutePageBuilderFunction()The same
transitionBuilder new withRouteTransitionBuilderFunction()The same
transitionDuration new withRouteTransitionDurationField()The same

Code sample

Define routing App

@router
class DemoApp extends StatefulWidget {
  @override
  _DemoAppState createState() => _DemoAppState();
}

class _DemoAppState extends State<DemoApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: "/", onGenerateRoute: onGenerateRoute, ); }}Copy the code

Defining the routing page

@initialPage
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    returnScaffold(); }}Copy the code

Define routing page parameters

  • For a single parameter

    @RoutePage(params: [RouteParameter("title")])
    class OneArgumentPage extends StatelessWidget {
      final String title;
    
      const OneArgumentPage({Key key, this.title}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        returnContainer(); }}Copy the code

    navigation

    Navigator.of(context).pushNamed(
      ROUTE_ONE_ARGUMENT_PAGE,
      arguments: "title is empty",);Copy the code

    Matters needing attention:

    For single-parameter routes, arguments are the original arguments for navigation using Navigator.

  • For multiple parameters

    @RoutePage(params: [RouteParameter("title"), RouteParameter("subTitle")])
    class TwoArgumentPage extends StatelessWidget {
      final String title;
      final String subTitle;
    
      TwoArgumentPage({this.title, Key key, this.subTitle}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        returnScaffold(); }}Copy the code

    navigation

    Navigator.of(context).pushNamed(
      ROUTE_TWO_ARGUMENT_PAGE,
      arguments: {
        "title": _titleController.text.isNotEmpty
            ? _titleController.text
            : "title is empty"."subTitle": _subTitleController.text.isNotEmpty
            ? _subTitleController.text
            : "sub title is empty",});Copy the code

    Matters needing attention:

    For routes with multiple parameters, arguments must be Map

    for navigation using Navigator.
    ,dynamic>

If you don’t need a custom route, you don’t need to add anything in the following sections and let route_generator generate the code for you.

Custom route (Priority: 3)

This route has the highest priority. If multiple user-defined routes exist at the same time, this route is selected first.

@page
class CustomRoutePage extends StatelessWidget {
  @routeField
  static Map<String, RouteFactory> route = <String, RouteFactory>{
    'custom_route': (RouteSettings settings) =>
        MaterialPageRoute(builder: (BuildContext context) => CustomRoutePage()),
    'alias_route': (RouteSettings settings) => PageRouteBuilder( pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) => CustomRoutePage(), ), }; . }Copy the code

It generates the following code:

Map<String, RouteFactory> _customRoutePage = CustomRoutePage.route;
Copy the code

Custom route (Priority: 2)

In this method, user-defined routes have a lower priority. If multiple user-defined routes exist at the same time, the routes are selected in descending order of priority.

@page
class CustomRoutePage extends StatelessWidget {
  @pageBuilder
  staticRoute buildPageRoute(RouteSettings settings) => PageRouteBuilder( pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) => CustomRoutePage(), ); . }Copy the code

It generates the following code:

Map<String, RouteFactory> _customRoutePage = <String, RouteFactory>{
  'custom_route_page': CustomRoutePage.buildPageRoute,
};
Copy the code

Custom route (Priority: 1)

In this method, the user-defined routes have the lowest priority. If multiple user-defined routes exist at the same time, the routes are selected in descending order of priority.

@page
class CustomRoutePage extends StatelessWidget {
  // The pageBuilder annotation indicates that this method is used to define how to return a RoutePage
  // It is optional
  @pageBuilder
  static Widget buildPage(BuildContext context, Animation animation,
          Animation secondaryAnimation, RouteSettings settings) =>
      CustomRoutePage();

  // The transitionBuilder annotation indicates that this method is used to define how to apply animation transitions
  // It is optional
  @transitionBuilder
  static Widget buildTransitions(
          BuildContext context,
          Animation<double> animation,
          Animation<double> secondaryAnimation,
          Widget child,
          RouteSettings settings) =>
      child;

  The transitionDuration annotation indicates that this field is used to define how long the page will be. The default is 300 milliseconds
  // It is optional
  @transitionDuration
  static Duration transitionDurations = Duration(milliseconds: 400); . }Copy the code

It generates the following code:

Map<String, RouteFactory> _customRoutePage = <String, RouteFactory>{
  'custom_route_page': (RouteSettings settings) => PageRouteBuilder(
        pageBuilder: (context, animation, secondaryAnimation) =>
            CustomRoutePage.buildPage(
                context, animation, secondaryAnimation, settings),
        transitionsBuilder: (context, animation, secondaryAnimation, child) =>
            CustomRoutePage.buildTransitions(
                context, animation, secondaryAnimation, child, settings),
        transitionDuration: CustomRoutePage.transitionDurations,
      ),
};
Copy the code

The routing code is automatically generated from the dependency packages in the pubspec.yaml file

  1. Create a new build.yaml file in the project root that needs to support automatic generation of routing code from dependencies in the pubspec.yaml file, skip this step if it already exists.

  2. Add the following to the file:

    # If you are sure that you only run `flutter pub run build_runner build`,
    # and don't run `flutter pub run build_runner watch`, then you can enable
    # the following comment out content.
    # targets:
    # $default:
    # builders:
    # route_generator|route_collector:
    # enabled: false
    
    # If you also want to enable source code generation for the packages of
    # dependencies in the pubspec.yaml, I think the following is what you need.
    builders:
      route_collector_all_packages:
        import: 'package:route_generator/builder.dart'
        builder_factories: ['routeCollectorAllPackages']
        build_extensions: { '.dart': ['.collector_all_packages.dart'] }
        auto_apply: all_packages
        runs_before: ["route_generator|route_builder"]
        build_to: cache
    Copy the code

    Notice Merge the same key parts.

  3. Rerun build_runner command

For more information, see Example

Questions about build_Runner Watch mode

  • Pubspec. yaml Dependencies Packages does not support continuous generation of routing code in Watch mode, but you can still enable watch mode in the current application. Post consideration support.

  • Since BuildStep does not support different outputs from the same file, that is, for each file, its output file is limited, so in Watch mode, if you modify the annotation information, you may need to refresh the file with the Route annotation once (you must make the file change and save, for example, adding blank lines). Dart will be regenerated. We are trying our best to solve it. The current scheme needs to be updated manually. If you have a better scheme, welcome to put forward.

Matters needing attention

  • Only one initalRoute is allowed
  • InitalRoute ignores the custom route name but generates a route nameROUTE_HOMERoute name constant of.
  • All custom route methods or getters must be defined in the route class and must be static and non-private.

Final generated code

Dart where FILENAME is the FILENAME of the App class annotated by the Router.

// GENERATED CODE - DO NOT MODIFY BY HAND

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// RouteGenerator
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

import 'package:flutter/material.dart';
import 'package:example_library/example_library.dart';
import 'package:example/custom_route_name_page.dart';
import 'package:example/custom_route_page.dart';
import 'package:example/home_page.dart';
import 'package:example/one_arguement_page.dart';
import 'package:example/two_arguement_page.dart';
import 'package:example/second_page.dart';

const ROUTE_LIBRARY_PAGE = 'library_page';
const ROUTE_CUSTOM = 'custom';
const ROUTE_CUSTOM_ROUTE_PAGE = 'custom_route_page';
const ROUTE_HOME = '/';
const ROUTE_ONE_ARGUMENT_PAGE = 'one_argument_page';
const ROUTE_TWO_ARGUMENT_PAGE = 'two_argument_page';
const ROUTE_SECOND_PAGE = 'second_page';

RouteFactory onGenerateRoute = (settings) => Map.fromEntries([
      ..._libraryPage.entries,
      ..._custom.entries,
      ..._customRoutePage.entries,
      ..._home.entries,
      ..._oneArgumentPage.entries,
      ..._twoArgumentPage.entries,
      ..._secondPage.entries,
    ])[settings.name](settings);

Map<String, RouteFactory> _libraryPage = <String, RouteFactory>{
  'library_page': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) => LibraryPage(),
      ),
};
Map<String, RouteFactory> _custom = <String, RouteFactory>{
  'custom': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) => CustomRoutePageName(),
      ),
};
Map<String, RouteFactory> _customRoutePage = CustomRoutePage.route;
Map<String, RouteFactory> _home = <String, RouteFactory>{
  '/': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) => HomePage(),
      ),
};
Map<String, RouteFactory> _oneArgumentPage = <String, RouteFactory>{
  'one_argument_page': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) =>
            OneArgumentPage(title: settings.arguments),
      ),
};
Map<String, RouteFactory> _twoArgumentPage = <String, RouteFactory>{
  'two_argument_page': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) {
          final arguments = settings.arguments as Map<String.dynamic>;
          return TwoArgumentPage(
            title: arguments['title'],
            subTitle: arguments['subTitle']); })};Map<String, RouteFactory> _secondPage = <String, RouteFactory>{
  'second_page': (RouteSettings settings) => MaterialPageRoute(
        builder: (BuildContext context) => SecondPage(),
      ),
};

Copy the code

Q&A

  • No routing file was generated

    Check that the Router annotations are added

  • Route generation is incomplete

    Try running the following command:

    • flutter pub run build_runner clean
    • flutter pub run build_runner build

Example

For more information, see Example