Flutter利用注解生成可自定义的路由的实现
route_generator是什么
这是一个简单的Flutter路由生成库,只需要少量的代码,然后利用注解配合源代码生成,自动生成路由表,省去手工管理路由代码的烦恼。
特性
- 自定义路由名称
- 自定义路由动画
- 自定义路由参数
- 自定义路由逻辑
依赖
dependencies: #Yourotherregulardependencieshere route_annotation:^0.1.0 dev_dependencies: #Yourotherdev_dependencieshere build_runner:^1.5.0 route_generator:^0.1.2
生成代码
单次构建
在项目根目录中运行flutterpubrunbuild_runnerbuild,可以在需要时为项目生成路由代码。这会触发一次性构建,该构建遍历源文件,选择相关文件,并为它们生成必要的路由代码。虽然这很方便,但如果您不必每次在模型类中进行更改时都必须手动构建,那么你可以选择持续构建。
持续构建
在项目根目录中运行flutterpubrunbuild_runnerwatch来启动watcher,它可以使我们的源代码生成过程更加方便。它会监视项目文件中的更改,并在需要时自动构建必要的文件。
route_annotation
| annotation | description |
|---|---|
| Router | 此注解用来标志某个为FlutterApp的类,并以此生成相应的路由代码 |
| RoutePage | 此注解用来注解一个路由页面 |
| RouteParameter | 一个用来标志页面参数的注解,只为可选参数设计。用于RoutePage。 |
| RouteField | 此注解用来标志一个完全自定义的路由,被注解的对象必须作为路由页面类静态字段 |
| PageRouteBuilderFuntcion | 这个注解用来标识一个路由页面的RouteFactory静态方法 |
| RoutePageBuilderFunction | 这个注解用来标识一个路由页面的RoutePageBuilder静态方法 |
| RouteTransitionBuilderFunction | 这个注解用来标识一个路由页面的TransitionBuilder静态方法 |
| RouteTransitionDurationField | 这个注解用来标识一个自定义路由页面的过渡时长 |
代码示例
定义路由App
@Router()
classDemoAppextendsStatefulWidget{
@override
_DemoAppStatecreateState()=>_DemoAppState();
}
class_DemoAppStateextendsState{
@override
Widgetbuild(BuildContextcontext){
returnMaterialApp(
initialRoute:"/",
onGenerateRoute:onGenerateRoute,
);
}
}
定义路由页面
//isInitialRoute为true表示它将作为initialpage
@RoutePage(isInitialRoute:true)
classHomePageextendsStatelessWidget{
@override
Widgetbuild(BuildContextcontext){
returnScaffold();
}
}
定义路由页面参数
对于单个参数
@RoutePage(params:[RouteParameter("title")])
classOneArgumentPageextendsStatelessWidget{
finalStringtitle;
constOneArgumentPage({Keykey,this.title}):super(key:key);
@override
Widgetbuild(BuildContextcontext){
returnContainer();
}
}
导航
Navigator.of(context).pushNamed( ROUTE_ONE_ARGUMENT_PAGE, arguments:"titleisempty", );
注意事项:
对于单个参数的路由,利用Navigator进行导航的时候arguments即为原始参数。
对于多个参数
@RoutePage(params:[RouteParameter("title"),RouteParameter("subTitle")])
classTwoArgumentPageextendsStatelessWidget{
finalStringtitle;
finalStringsubTitle;
TwoArgumentPage({this.title,Keykey,this.subTitle}):super(key:key);
@override
Widgetbuild(BuildContextcontext){
returnScaffold();
}
}
导航
Navigator.of(context).pushNamed(
ROUTE_TWO_ARGUMENT_PAGE,
arguments:{
"title":_titleController.text.isNotEmpty
?_titleController.text
:"titleisempty",
"subTitle":_subTitleController.text.isNotEmpty
?_subTitleController.text
:"subtitleisempty",
},
);
注意事项:
对于多个参数的路由,利用Navigator进行导航的时候arguments必须为Map
如果你不需要自定义路由,以下部分,你可以什么都不用添加,就让route_generator为你自动生成相关代码吧!
自定义路由(优先级:3)
这种方法自定义路由的优先级最高,如果同时存在多种自定义路由选择,该种方案最先被选择。
@RoutePage()
classCustomRoutePageextendsStatelessWidget{
@RouteField()
staticMaproute={
'custom_route':(RouteSettingssettings)=>
MaterialPageRoute(builder:(BuildContextcontext)=>CustomRoutePage()),
'alias_route':(RouteSettingssettings)=>PageRouteBuilder(
pageBuilder:(BuildContextcontext,Animationanimation,
AnimationsecondaryAnimation)=>
CustomRoutePage(),
),
};
...
}
它会生成如下代码:
Map_customRoutePage=CustomRoutePage.route;
自定义路由(优先级:2)
这种方法自定义路由的优先级较低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。
@RoutePage()
classCustomRoutePageextendsStatelessWidget{
@PageRouteBuilderFuntcion()
staticRoutebuildPageRoute(RouteSettingssettings)=>PageRouteBuilder(
pageBuilder:(BuildContextcontext,Animationanimation,
AnimationsecondaryAnimation)=>
CustomRoutePage(),
);
...
}
它会生成如下代码:
Map_customRoutePage= { 'custom_route_page':CustomRoutePage.buildPageRoute, };
自定义路由(优先级:1)
这种方法自定义路由的优先级最低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。
@RoutePage()
classCustomRoutePageextendsStatelessWidget{
//RoutePageBuilderFunction注解表明这个方法用来定义如何返回RoutePage
//它是可选的
@RoutePageBuilderFunction()
staticWidgetbuildPage(BuildContextcontext,Animationanimation,
AnimationsecondaryAnimation,RouteSettingssettings)=>
CustomRoutePage();
//RouteTransitionBuilderFunction注解表明这个方法用来定义如何应用动画过渡
//它是可选的
@RouteTransitionBuilderFunction()
staticWidgetbuildTransitions(
BuildContextcontext,
Animationanimation,
AnimationsecondaryAnimation,
Widgetchild,
RouteSettingssettings)=>
child;
//RouteTransitionDurationField注解表明这个字段用来定义页面过渡时常长,默认值为300milliseconds
//它是可选的
@RouteTransitionDurationField()
staticDurationtransitionDuration=Duration(milliseconds:400);
...
}
它会生成如下代码:
Map_customRoutePage= { 'custom_route_page':(RouteSettingssettings)=>PageRouteBuilder( pageBuilder:(context,animation,secondaryAnimation)=> CustomRoutePage(), transitionsBuilder:(context,animation,secondaryAnimation,child)=> CustomRoutePage.buildTransitions( context,animation,secondaryAnimation,child,settings), transitionDuration:CustomRoutePage.transitionDuration, ), };
注意事项
- 只允许有一个initalRoute
- initalRoute会忽略自定义路由名,但会生成名为ROUTE_HOME的路由名称常量。
- 所有自定义路由method或getter必须定义在路由所在类,且必须为static所修饰的和非私有的。
最终生成代码
最终生成的文件名为FILENAME.route.dart
其中FILENAME是被Router注解的App类所在的文件名。
//GENERATEDCODE-DONOTMODIFYBYHAND //************************************************************************** //RouteGenerator //************************************************************************** import'package:flutter/material.dart'; import'home_page.dart'; import'custom_route_page.dart'; import'custom_route_name_page.dart'; import'second_page.dart'; import'one_arguement_page.dart'; import'two_arguement_page.dart'; constROUTE_HOME='/'; constROUTE_CUSTOM_ROUTE_PAGE='custom_route_page'; constROUTE_CUSTOM='custom'; constROUTE_SECOND_PAGE='second_page'; constROUTE_ONE_ARGUMENT_PAGE='one_argument_page'; constROUTE_TWO_ARGUMENT_PAGE='two_argument_page'; RouteFactoryonGenerateRoute=(settings)=>Map.fromEntries([ ..._home.entries, ..._customRoutePage.entries, ..._custom.entries, ..._secondPage.entries, ..._oneArgumentPage.entries, ..._twoArgumentPage.entries, ])[settings.name](settings); Map_home= { '/':(RouteSettingssettings)=>MaterialPageRoute( builder:(BuildContextcontext)=>HomePage(), ), }; Map _customRoutePage= { 'custom_route_page':(RouteSettingssettings)=>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.transitionDuration, ), }; Map _custom= { 'custom':(RouteSettingssettings)=>MaterialPageRoute( builder:(BuildContextcontext)=>CustomRoutePageName(), ), }; Map _secondPage= { 'second_page':(RouteSettingssettings)=>MaterialPageRoute( builder:(BuildContextcontext)=>SecondPage(), ), }; Map _oneArgumentPage= { 'one_argument_page':(RouteSettingssettings)=>MaterialPageRoute( builder:(BuildContextcontext)=> OneArgumentPage(title:settings.arguments), ), }; Map _twoArgumentPage= { 'two_argument_page':(RouteSettingssettings)=>MaterialPageRoute( builder:(BuildContextcontext)=>TwoArgumentPage( title:(settings.argumentsasMap )['title'], subTitle: (settings.argumentsasMap )['subTitle'], ), ), };
常见问题
没有生成路由文件
请检查是否添加了Router注解
Example
获取更详细信息,请参阅example
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。