- What is it
- Features
- Depend on it
- Running the code generation utility
- route_annotation
- Example code
- Custom route (priority: 3)
- Custom route (priority: 2)
- Custom route (priority: 1)
- Automatically generate routing code from dependency packages in the pubspec.yaml file
- About the problem in build_runner watch mode
- Warning
- Generated code
- Common problem
This is a route generation library.Only a small amount of code is required,then use the annotation to match the source code generation, automatically generate the routing table.
- Custom route name.
- Custom route animations.
- Custom route parameters.
- Custom route logic.
- Automatically generate routing code from dependency packages in the pubspec.yaml file
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
-
One-time code generation
By running
flutter pub run build_runner build
in the project root,you generate routing code for your application whenever they are needed. This triggers a one-time build that goes through the source files, picks the relevant ones, and generates the necessary routing code for them.While this is convenient, it would be nice if you did not have to run the build manually every time you make changes in your routing page classes.
-
Generating code continuously
A watcher makes our source code generation process more convenient. It watches changes in our project files and automatically builds the necessary files when needed. Start the watcher by running
flutter pub run build_runner watch
in the project root.It is safe to start the watcher once and leave it running in the background.
annotation | description |
---|---|
Router |
This annotation is used to mark a class that is a Flutter App and use this to generate the corresponding routing code. |
RoutePage |
This annotation is used to annotate a routing page |
RouteParameter |
An annotation used to mark page parameters is only designed for optional parameters. Used for RoutePage . |
RouteField |
This annotation is used to mark a completely custom route, and the annotated object must be used as a static field of the route page class. |
PageRouteBuilderFuntcion |
This annotation is used to identify the RouteFactory static method of a routing page. |
RoutePageBuilderFunction |
This annotation is used to identify the RoutePageBuilder static method of a routing page. |
RouteTransitionBuilderFunction |
This annotation is used to identify the TransitionBuilder static method of a routing page. |
RouteTransitionDurationField |
This annotation is used to identify the transition time of a custom routing page. |
router new |
Same as Router() |
page new |
Same as RoutePage() |
initialPage new |
Same as RoutePage(isInitialRoute: true) |
routeField new |
Same as RouteField() |
routeBuilder new |
Same as PageRouteBuilderFuntcion() |
pageBuilder new |
Same as RoutePageBuilderFunction() |
transitionBuilder new |
Same as RouteTransitionBuilderFunction() |
transitionDuration new |
Same as RouteTransitionDurationField() |
@router
class DemoApp extends StatefulWidget {
@override
_DemoAppState createState() => _DemoAppState();
}
class _DemoAppState extends State<DemoApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/",
onGenerateRoute: onGenerateRoute,
);
}
}
@initialPage
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold();
}
}
-
For 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) { return Container(); } }
Navigation:
Navigator.of(context).pushNamed( ROUTE_ONE_ARGUMENT_PAGE, arguments: "title is empty", );
Warning:
For the route of a single parameter, the
arguments
is the raw argument when navigating with the 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) { return Scaffold(); } }
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", }, );
Warning:
For the route of multiple parameters, the
arguments
must beMap<string,dynamic>
when navigating with Navigator.
If you don't need custom routing, the following sections, you can add nothing, let route_generator automatically generate relevant code for you!
This method has the highest priority for custom routing. If there are multiple custom routing options at the same time, this plan 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(),
),
};
...
}
It will generate the following code:
Map<String, RouteFactory> _customRoutePage = CustomRoutePage.route;
This method has a lower priority for custom routing. If there are multiple custom routing options at the same time, the plan is selected by priority from large to small.
@page
class CustomRoutePage extends StatelessWidget {
@pageBuilder
static Route buildPageRoute(RouteSettings settings) => PageRouteBuilder(
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) =>
CustomRoutePage(),
);
...
}
It will generate the following code:
Map<String, RouteFactory> _customRoutePage = <String, RouteFactory>{
'custom_route_page': CustomRoutePage.buildPageRoute,
};
This method has the lowest priority for custom routing. If there are multiple custom routing options at the same time, the plan is selected by priority from large to small.
@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 use animations.
/// 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 the length of the page transition. The
/// default value is 300 milliseconds.
/// It is optional
@transitionDuration
static Duration transitionDuration = Duration(milliseconds: 400);
...
}
It will generate 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,
),
};
-
In the project root directory that needs to support automatic generation of routing code from the dependencies in the pubspec.yaml file, create a new build.yaml file, skip this step if it already exists.
-
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
Note that the same key parts should be merged.
-
Re-run the build_runner command
For more details, please see example
-
Need to know is: pubspec.yaml dependencies packages does not support watch mode to continuously generate routing code (the first generation is still valid), but you can still enable watch mode in the current application. Consider support later.
-
Since BuildStep does not support different output of the same file, that is, for each file, its output file is limited, so in watch mode, if you modify the annotation information, then you may need to refresh the file where the Route annotation is located (The file must be changed and saved, such as adding a blank line), to regenerate xxx.route.dart. We are trying our best to solve it. The current plan needs to be refreshed manually. If you have a better solution, please feel free to ask.
- Only one initalRoute is allowed
- initalRoute ignores custom route name,but generates a route name constant named
ROUTE_HOME
. - All custom route methods or getters must be defined in the class of the route page and must be static and public.
The file name is filename.route.dart
Where filename is the file name of the Application class annotated by 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(),
),
};
-
No file generated
Please check if the Router annotation has been added
-
The generated route is incomplete
Please try running the following command:
- flutter pub run build_runner clean
- flutter pub run build_runner build
For more details, please see example