Flutter利用注解生成可自定義的路由的實現(xiàn)
route_generator是什么
這是一個簡單的 Flutter 路由生成庫,只需要少量的代碼,然后利用注解配合源代碼生成,自動生成路由表,省去手工管理路由代碼的煩惱。
特性
- 自定義路由名稱
- 自定義路由動畫
- 自定義路由參數(shù)
- 自定義路由邏輯
依賴
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
生成代碼
單次構(gòu)建
在項目根目錄中運行flutter pub run build_runner build,可以在需要時為項目生成路由代碼。這會觸發(fā)一次性構(gòu)建,該構(gòu)建遍歷源文件,選擇相關(guān)文件,并為它們生成必要的路由代碼。雖然這很方便,但如果您不必每次在模型類中進行更改時都必須手動構(gòu)建,那么你可以選擇持續(xù)構(gòu)建。
持續(xù)構(gòu)建
在項目根目錄中運行flutter pub run build_runner watch來啟動watcher,它可以使我們的源代碼生成過程更加方便。它會監(jiān)視項目文件中的更改,并在需要時自動構(gòu)建必要的文件。
route_annotation
| annotation | description |
|---|---|
| Router | 此注解用來標(biāo)志某個為 Flutter App 的類,并以此生成相應(yīng)的路由代碼 |
| RoutePage | 此注解用來注解一個路由頁面 |
| RouteParameter | 一個用來標(biāo)志頁面參數(shù)的注解,只為可選參數(shù)設(shè)計。用于 RoutePage 。 |
| RouteField | 此注解用來標(biāo)志一個完全自定義的路由,被注解的對象必須作為路由頁面類靜態(tài)字段 |
| PageRouteBuilderFuntcion | 這個注解用來標(biāo)識一個路由頁面的 RouteFactory 靜態(tài)方法 |
| RoutePageBuilderFunction | 這個注解用來標(biāo)識一個路由頁面的 RoutePageBuilder靜態(tài)方法 |
| RouteTransitionBuilderFunction | 這個注解用來標(biāo)識一個路由頁面的 TransitionBuilder 靜態(tài)方法 |
| RouteTransitionDurationField | 這個注解用來標(biāo)識一個自定義路由頁面的過渡時長 |
代碼示例
定義路由 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();
}
}
定義路由頁面參數(shù)
對于單個參數(shù)
@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();
}
}
導(dǎo)航
Navigator.of(context).pushNamed( ROUTE_ONE_ARGUMENT_PAGE, arguments: "title is empty", );
注意事項:
對于單個參數(shù)的路由,利用Navigator進行導(dǎo)航的時候arguments即為原始參數(shù)。
對于多個參數(shù)
@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();
}
}
導(dǎo)航
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",
},
);
注意事項:
對于多個參數(shù)的路由,利用Navigator進行導(dǎo)航的時候arguments必須為Map<string,dynamic>。
如果你不需要自定義路由,以下部分,你可以什么都不用添加,就讓route_generator為你自動生成相關(guān)代碼吧!
自定義路由(優(yōu)先級:3)
這種方法自定義路由的優(yōu)先級最高,如果同時存在多種自定義路由選擇,該種方案最先被選擇。
@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;
自定義路由(優(yōu)先級:2)
這種方法自定義路由的優(yōu)先級較低,如果同時存在多種自定義路由選擇,則按優(yōu)先級從大到小選擇。
@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,
};
自定義路由(優(yōu)先級:1)
這種方法自定義路由的優(yōu)先級最低,如果同時存在多種自定義路由選擇,則按優(yōu)先級從大到小選擇。
@RoutePage()
class CustomRoutePage extends StatelessWidget {
// RoutePageBuilderFunction注解表明這個方法用來定義如何返回RoutePage
// 它是可選的
@RoutePageBuilderFunction()
static Widget buildPage(BuildContext context, Animation animation,
Animation secondaryAnimation, RouteSettings settings) =>
CustomRoutePage();
// RouteTransitionBuilderFunction注解表明這個方法用來定義如何應(yīng)用動畫過渡
// 它是可選的
@RouteTransitionBuilderFunction()
static Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
RouteSettings settings) =>
child;
// RouteTransitionDurationField注解表明這個字段用來定義頁面過渡時常長,默認(rèn)值為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
獲取更詳細(xì)信息,請參閱example
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Flutter路由框架Fluro使用簡介
- Flutter如何完成路由攔截,實現(xiàn)權(quán)限管理
- Flutter開發(fā)中的路由參數(shù)處理
- Flutter app頁面路由以及路由攔截的實現(xiàn)
- 詳解Flutter的路由導(dǎo)航
- flutter 路由跳轉(zhuǎn)的實現(xiàn)示例
- flutter 自定義websocket路由的實現(xiàn)
- Flutter開發(fā)之路由與導(dǎo)航的實現(xiàn)
- Flutter上線項目實戰(zhàn)記錄之路由篇
- Flutter 局部路由實現(xiàn)詳解
- Flutter路由的跳轉(zhuǎn)、動畫和傳參詳解(最簡單)
- Flutter 路由插件fluro的使用
相關(guān)文章
Android之用PopupWindow實現(xiàn)彈出菜單的方法詳解
本篇文章是對在Android中,用PopupWindow實現(xiàn)彈出菜單的方法進行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
Android自定義View實現(xiàn)loading動畫加載效果
項目開發(fā)中對Loading的處理是比較常見的,安卓系統(tǒng)提供的不太美觀,引入第三發(fā)又太麻煩,這時候自己定義View來實現(xiàn)這個效果。這篇文章主要介紹了Android自定義View實現(xiàn)loading動畫加載效果,需要的朋友可以參考下2017-03-03
android使用ExpandableListView控件實現(xiàn)小說目錄效果的例子
這篇文章主要介紹了android使用ExpandableListView控件實現(xiàn)小說目錄效果的例子,還可以實現(xiàn)二級列表展示效果,需要的朋友可以參考下2014-07-07
Kotlin中ListView與RecyclerView的應(yīng)用講解
這篇文章主要介紹了Kotlin中ListView與RecyclerView的應(yīng)用講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
Android使用TextView實現(xiàn)無下劃線超鏈接的方法
這篇文章主要介紹了Android使用TextView實現(xiàn)無下劃線超鏈接的方法,結(jié)合實例形式分析了Android中TextView超鏈接去除下劃線的相關(guān)實現(xiàn)技巧與注意事項,需要的朋友可以參考下2016-08-08

