本节目标

  • 安装插件
  • 路由定义
  • 自动生成路由控制类
  • 转场动画
  • 登录检查中间件
  • 带参数传递
  • 获取返回值

视频

代码

https://github.com/ducafecat/flutter_learn_news/releases/tag/v1.0.8

正文

一些优秀的路由插件

  • fluro

    前端的使用体验

    router.navigateTo(context, “/users/1234”, transition: TransitionType.fadeIn);

  • flutter_modular

    功能强大的路由管理:中间件、懒加载、状态管理、动态路由、分组路由、动画、返回值、命名路由

  • auto_route

    设计精简、低耦合其它功能

    功能:中间件、自动生成路由代码、动态路由、动画、返回值、命名路由

安装插件

  • 官网

https://pub.flutter-io.cn/packages/auto_route

  • pubspec.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
dependencies:
flutter:
sdk: flutter

# 路由管理
auto_route: ^0.4.4

dev_dependencies:
flutter_test:
sdk: flutter

# 路由生成
auto_route_generator: ^0.4.4
build_runner:

路由定义

  • lib/common/router/router.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@MaterialAutoRouter()
class $AppRouter {
@initial
IndexPage indexPageRoute;

WelcomePage welcomePageRoute;

SignInPage signInPageRoute;

SignUpPage signUpPageRoute;

ApplicationPage applicationPageRoute;

DetailsPage detailsPageRoute;
}

注意 $ 符号

自动生成路由控制类

  • 执行命令
1
flutter packages pub run build_runner build
  • 自动生成 lib/common/router/router.gr.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// AutoRouteGenerator
// **************************************************************************

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter_ducafecat_news/pages/index/index.dart';
import 'package:flutter_ducafecat_news/pages/welcome/welcome.dart';
import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart';
import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart';
import 'package:flutter_ducafecat_news/pages/application/application.dart';
import 'package:flutter_ducafecat_news/common/router/auth_grard.dart';
import 'package:flutter_ducafecat_news/pages/details/details.dart';

abstract class Routes {
static const indexPageRoute = '/';
static const welcomePageRoute = '/welcome-page-route';
static const signInPageRoute = '/sign-in-page-route';
static const signUpPageRoute = '/sign-up-page-route';
static const applicationPageRoute = '/application-page-route';
static const detailsPageRoute = '/details-page-route';
}

class AppRouter extends RouterBase {
@override
Map<String, List<Type>> get guardedRoutes => {
Routes.applicationPageRoute: [AuthGuard],
Routes.detailsPageRoute: [AuthGuard],
};

//This will probably be removed in future versions
//you should call ExtendedNavigator.ofRouter<Router>() directly
static ExtendedNavigatorState get navigator =>
ExtendedNavigator.ofRouter<AppRouter>();

@override
Route<dynamic> onGenerateRoute(RouteSettings settings) {
final args = settings.arguments;
switch (settings.name) {
case Routes.indexPageRoute:
if (hasInvalidArgs<IndexPageArguments>(args)) {
return misTypedArgsRoute<IndexPageArguments>(args);
}
final typedArgs = args as IndexPageArguments ?? IndexPageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => IndexPage(key: typedArgs.key),
settings: settings,
);
case Routes.welcomePageRoute:
if (hasInvalidArgs<WelcomePageArguments>(args)) {
return misTypedArgsRoute<WelcomePageArguments>(args);
}
final typedArgs =
args as WelcomePageArguments ?? WelcomePageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => WelcomePage(key: typedArgs.key),
settings: settings,
);
case Routes.signInPageRoute:
if (hasInvalidArgs<SignInPageArguments>(args)) {
return misTypedArgsRoute<SignInPageArguments>(args);
}
final typedArgs = args as SignInPageArguments ?? SignInPageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => SignInPage(key: typedArgs.key),
settings: settings,
);
case Routes.signUpPageRoute:
if (hasInvalidArgs<SignUpPageArguments>(args)) {
return misTypedArgsRoute<SignUpPageArguments>(args);
}
final typedArgs = args as SignUpPageArguments ?? SignUpPageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => SignUpPage(key: typedArgs.key),
settings: settings,
);
case Routes.applicationPageRoute:
if (hasInvalidArgs<ApplicationPageArguments>(args)) {
return misTypedArgsRoute<ApplicationPageArguments>(args);
}
final typedArgs =
args as ApplicationPageArguments ?? ApplicationPageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => ApplicationPage(key: typedArgs.key),
settings: settings,
);
case Routes.detailsPageRoute:
if (hasInvalidArgs<DetailsPageArguments>(args)) {
return misTypedArgsRoute<DetailsPageArguments>(args);
}
final typedArgs =
args as DetailsPageArguments ?? DetailsPageArguments();
return MaterialPageRoute<dynamic>(
builder: (_) => DetailsPage(key: typedArgs.key),
settings: settings,
);
default:
return unknownRoutePage(settings.name);
}
}
}

//**************************************************************************
// Arguments holder classes
//***************************************************************************

//IndexPage arguments holder class
class IndexPageArguments {
final Key key;
IndexPageArguments({this.key});
}

//WelcomePage arguments holder class
class WelcomePageArguments {
final Key key;
WelcomePageArguments({this.key});
}

//SignInPage arguments holder class
class SignInPageArguments {
final Key key;
SignInPageArguments({this.key});
}

//SignUpPage arguments holder class
class SignUpPageArguments {
final Key key;
SignUpPageArguments({this.key});
}

//ApplicationPage arguments holder class
class ApplicationPageArguments {
final Key key;
ApplicationPageArguments({this.key});
}

//DetailsPage arguments holder class
class DetailsPageArguments {
final Key key;
DetailsPageArguments({this.key});
}

路由跳转

  • 方式 1:带 context 方式
1
ExtendedNavigator.of(context).pushNamed(Routes.signUpPageRoute);
  • 方式 2:不带 context 方式
1
ExtendedNavigator.ofRouter<AppRouter>().pushNamed(Routes.signUpPageRoute);
  • 方式 3:如果你只有一个导航
1
ExtenedNavigator.rootNavigator.pushNamed(Routes.signUpPageRoute);

转场动画

  • lib/common/router/router.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Widget zoomInTransition(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
// you get an animation object and a widget
// make your own transition
return ScaleTransition(scale: animation, child: child);
}

@MaterialAutoRouter()
class $AppRouter {
...

@CustomRoute(transitionsBuilder: zoomInTransition)
ApplicationPage applicationPageRoute;
}
  • 重新生成
1
flutter packages pub run build_runner build

登录检查中间件

  • 创建 lib/common/router/auth_grard.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import 'package:auto_route/auto_route.dart';
import 'package:flutter_ducafecat_news/common/router/router.gr.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';

class AuthGuard extends RouteGuard {
@override
Future<bool> canNavigate(ExtendedNavigatorState navigator, String routeName,
Object arguments) async {
var isAuth = await isAuthenticated();
if (isAuth == false) {
ExtendedNavigator.rootNavigator.pushNamed(Routes.signInPageRoute);
}

return isAuth;
}
}
  • 注册 lib/main.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ducafecat.tech',
debugShowCheckedModeBanner: false,
builder: ExtendedNavigator<AppRouter>(
initialRoute: Routes.indexPageRoute,
router: AppRouter(),
guards: [AuthGuard()],
),
);
}
}
  • 定义 lib/common/router/router.dart
1
2
3
4
5
6
7
8
@MaterialAutoRouter()
class $AppRouter {
...

@GuardedBy([AuthGuard])
@CustomRoute(transitionsBuilder: zoomInTransition)
ApplicationPage applicationPageRoute;
}
  • 重新生成
1
flutter packages pub run build_runner build

参数传递

  • 设定初始参数 lib/pages/details/details.dart
1
2
3
class DetailsPage extends StatefulWidget {
final String cid;
DetailsPage({Key key, this.cid}) : super(key: key);
  • 定义 lib/common/router/router.dart
1
2
3
@MaterialAutoRouter(generateNavigationHelperExtension: true)
class $AppRouter {
...
  • 重新生成
1
flutter packages pub run build_runner build
  • lib/common/router/router.gr.dart
1
2
3
4
5
6
//DetailsPage arguments holder class
class DetailsPageArguments {
final Key key;
final String cid;
DetailsPageArguments({this.key, this.cid});
}
  • 导航参数
1
ExtendedNavigator.rootNavigator.pushDetailsPageRoute(cid: '123');
  • 获取返回值
1
2
3
4
5
ExtendedNavigator.rootNavigator
.pushNamed(Routes.signUpPageRoute)
.then((onValue) {
print(onValue);
});

资源

视频

蓝湖设计稿(加微信给授权 ducafecat)

https://lanhuapp.com/url/lYuz1
密码: gSKl

蓝湖现在收费了,所以查看标记还请自己上传 xd 设计稿
商业设计稿文件不好直接分享, 可以加微信联系 ducafecat

YAPI 接口管理

http://yapi.demo.qunar.com/

参考

https://pub.flutter-io.cn/packages/auto_route

VSCode 插件


© 猫哥

https://ducafecat.tech