Flutter利用注解生成可自定义的路由的实现
route_generator是什么
这是一个简单的 flutter 路由生成库,只需要少量的代码,然后利用注解配合源代码生成,自动生成路由表,省去手工管理路由代码的烦恼。
特性
- 自定义路由名称
- 自定义路由动画
- 自定义路由参数
- 自定义路由逻辑
依赖
dependencies: # your other regular dependencies here route_annotation: ^0.1.0 dev_dependencies: # your other dev_dependencies here build_runner: ^1.5.0 route_generator: ^0.1.2
生成代码
单次构建
在项目根目录中运行flutter pub run build_runner build,可以在需要时为项目生成路由代码。这会触发一次性构建,该构建遍历源文件,选择相关文件,并为它们生成必要的路由代码。虽然这很方便,但如果您不必每次在模型类中进行更改时都必须手动构建,那么你可以选择持续构建。
持续构建
在项目根目录中运行flutter pub run build_runner watch来启动watcher,它可以使我们的源代码生成过程更加方便。它会监视项目文件中的更改,并在需要时自动构建必要的文件。
route_annotation
annotation | description |
---|---|
router | 此注解用来标志某个为 flutter app 的类,并以此生成相应的路由代码 |
routepage | 此注解用来注解一个路由页面 |
routeparameter | 一个用来标志页面参数的注解,只为可选参数设计。用于 routepage 。 |
routefield | 此注解用来标志一个完全自定义的路由,被注解的对象必须作为路由页面类静态字段 |
pageroutebuilderfuntcion | 这个注解用来标识一个路由页面的 routefactory 静态方法 |
routepagebuilderfunction | 这个注解用来标识一个路由页面的 routepagebuilder静态方法 |
routetransitionbuilderfunction | 这个注解用来标识一个路由页面的 transitionbuilder 静态方法 |
routetransitiondurationfield | 这个注解用来标识一个自定义路由页面的过渡时长 |
代码示例
定义路由 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, ); } }
定义路由页面
// isinitialroute为true表示它将作为initial page @routepage(isinitialroute: true) class homepage extends statelesswidget { @override widget build(buildcontext context) { return scaffold(); } }
定义路由页面参数
对于单个参数
@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(); } }
导航
navigator.of(context).pushnamed( route_one_argument_page, arguments: "title is empty", );
注意事项:
对于单个参数的路由,利用navigator进行导航的时候arguments即为原始参数。
对于多个参数
@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(); } }
导航
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", }, );
注意事项:
对于多个参数的路由,利用navigator进行导航的时候arguments必须为map<string,dynamic>。
如果你不需要自定义路由,以下部分,你可以什么都不用添加,就让route_generator为你自动生成相关代码吧!
自定义路由(优先级:3)
这种方法自定义路由的优先级最高,如果同时存在多种自定义路由选择,该种方案最先被选择。
@routepage() 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(), ), }; ... }
它会生成如下代码:
map<string, routefactory> _customroutepage = customroutepage.route;
自定义路由(优先级:2)
这种方法自定义路由的优先级较低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。
@routepage() class customroutepage extends statelesswidget { @pageroutebuilderfuntcion() static route buildpageroute(routesettings settings) => pageroutebuilder( pagebuilder: (buildcontext context, animation animation, animation secondaryanimation) => customroutepage(), ); ... }
它会生成如下代码:
map<string, routefactory> _customroutepage = <string, routefactory>{ 'custom_route_page': customroutepage.buildpageroute, };
自定义路由(优先级:1)
这种方法自定义路由的优先级最低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。
@routepage() class customroutepage extends statelesswidget { // routepagebuilderfunction注解表明这个方法用来定义如何返回routepage // 它是可选的 @routepagebuilderfunction() static widget buildpage(buildcontext context, animation animation, animation secondaryanimation, routesettings settings) => customroutepage(); // routetransitionbuilderfunction注解表明这个方法用来定义如何应用动画过渡 // 它是可选的 @routetransitionbuilderfunction() static widget buildtransitions( buildcontext context, animation<double> animation, animation<double> secondaryanimation, widget child, routesettings settings) => child; // routetransitiondurationfield注解表明这个字段用来定义页面过渡时常长,默认值为300 milliseconds // 它是可选的 @routetransitiondurationfield() static duration transitionduration = duration(milliseconds: 400); ... }
它会生成如下代码:
map<string, routefactory> _customroutepage = <string, routefactory>{ 'custom_route_page': (routesettings settings) => 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类所在的文件名。
// generated code - do not modify by hand // ************************************************************************** // 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'; const route_home = '/'; const route_custom_route_page = 'custom_route_page'; const route_custom = 'custom'; const route_second_page = 'second_page'; const route_one_argument_page = 'one_argument_page'; const route_two_argument_page = 'two_argument_page'; routefactory ongenerateroute = (settings) => map.fromentries([ ..._home.entries, ..._customroutepage.entries, ..._custom.entries, ..._secondpage.entries, ..._oneargumentpage.entries, ..._twoargumentpage.entries, ])[settings.name](settings); map<string, routefactory> _home = <string, routefactory>{ '/': (routesettings settings) => materialpageroute( builder: (buildcontext context) => homepage(), ), }; 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.transitionduration, ), }; map<string, routefactory> _custom = <string, routefactory>{ 'custom': (routesettings settings) => materialpageroute( builder: (buildcontext context) => customroutepagename(), ), }; map<string, routefactory> _secondpage = <string, routefactory>{ 'second_page': (routesettings settings) => materialpageroute( builder: (buildcontext context) => secondpage(), ), }; 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) => twoargumentpage( title: (settings.arguments as map<string, dynamic>)['title'], subtitle: (settings.arguments as map<string, dynamic>)['subtitle'], ), ), };
常见问题
没有生成路由文件
请检查是否添加了router注解
example
获取更详细信息,请参阅
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。