本文是 1.6 系列版本的用法,1.7后使用方式有所改变,它启用了新的类型 FluroRouter 来替代之前的 Router,相应的使用的 Router 类型需要替换为 FluroRouter。
正文开始:
Flutter的路由机制很烦琐,如果是小型应用还勉强适用,但是真实开发中我们都会使用企业级的路由机制,让路由清晰可用。
Fluro是比较好的企业级Flutter路由。官方有使用介绍: https://pub.flutter-io.cn/packages/fluro 但是介绍的还不够详细。下面根据实战来记录下 Fluro 的使用姿势,分为两部分,第一部分是解释官网的使用步骤。第二部分是在实际项目中的一般使用步骤。
第一部分,解释官网的使用步骤,Fluro 按照官网的教程来看,步骤如下
1、在工程里引入 Fluro,在项目的 pubspec.yaml 内引入:
dependencies:
fluro: "^1.6.3"
记得 pubspec.yaml 修改后,需要执行flutter命令 flutter pub get 一下哦。把包都下载进项目里才能使用。
2、在项目内实例化 Fluro 的一个路由实例出来:
import 'package:fluro/fluro.dart';
final router = Router();
3、为这个路由定义 路由名称 和 对应路由名称的处理逻辑:
定义路由:(这里 handler 传入的 是下面定义的那个处理程序usersHandler,意思就是 访问路由是”/users/:id” 则执行usersHandler这个处理操作)
router.define("/users/:id", handler: usersHandler);
处理程序:(这个处理程序是 返回 UsersScreen 这个组件)
处理路由逻辑的handler:(此处示例 handler 是 返回 UsersScreen 这个我们自定义的组件)
var usersHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
//...这里还可以进行一些操作,反正最后 return 一个我们路由跳转后需要显示的组件就OK
return UsersScreen(params["id"][0]);
});
至此,配置就完成了,路由器将拦截诸如之类的 /users/1234 路由,并将应用程序路由至 UsersScreen 将值 1234 作为参数传递给该屏幕的路由。以此类推,我们可以定义许多 不同路由的 处理。
4、那接下来怎么让项目使用上路由呢?如下:
在 MaterialApp 的配置参数中,设置 onGenerateRoute: router.generator。
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo', //任务管理上显示的名字
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
onGenerateRoute: router.generator, //这里配置使用 Fluro
……
这个 onGenerateRoute 参数是在“当跳转 命名路由 时找不到该路由,就会调用该方法”,所以这个 Fluro 其实就是通过自己封装的路由处理逻辑,然后在这里进行 各个路由的判断,然后根据判断返回不同的页面 来实现路由跳转的。
5、项目里进行路由跳转:
接下来,就可以用 Navigator.push 来跳转路由了。也可以自己手动推送到路线:
router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);
transition 是跳转动画,它是可选命名参数,它还有一些值,比如 c: TransitionType.inFromLeft 等等,详见 transitionType 的定义源码如下:
enum TransitionType {
native,
nativeModal,
inFromLeft,
inFromRight,
inFromBottom,
fadeIn,
custom, // if using custom then you must also provide a transition
material,
materialFullScreenDialog,
cupertino,
cupertinoFullScreenDialog,
}
另外,navigateTo 方法还有一些可选命名参数,下面源码的2-6行的参数,根据需要选择使用即可,比如那个 transitionDuration 就是表示路由跳转动画过渡的时间,clearStack 表示跳转后是否清除路由栈等等:
Future navigateTo(BuildContext context, String path,
{bool replace = false,
bool clearStack = false,
TransitionType transition,
Duration transitionDuration = const Duration(milliseconds: 250),
RouteTransitionsBuilder transitionBuilder}) {
RouteMatch routeMatch = matchRoute(context, path,
transitionType: transition,
transitionsBuilder: transitionBuilder,
transitionDuration: transitionDuration);
Route<dynamic> route = routeMatch.route;
Completer completer = Completer();
Future future = completer.future;
if (routeMatch.matchType == RouteMatchType.nonVisual) {
completer.complete("Non visual route type.");
} else {
if (route == null && notFoundHandler != null) {
route = _notFoundRoute(context, path);
}
if (route != null) {
if (clearStack) {
future =
Navigator.pushAndRemoveUntil(context, route, (check) => false);
} else {
future = replace
? Navigator.pushReplacement(context, route)
: Navigator.push(context, route);
}
completer.complete();
} else {
String error = "No registered route was found to handle '$path'.";
print(error);
completer.completeError(RouteNotFoundException(error, path));
}
}
return future;
}
第二部分,项目中实际应用
1、一般我们把第一部分的第二步实例化的 router 放入一个类里来定义,把 Fluro 的 Router 静态化,方便今后项目里全局调用:创建一个 Application 类
import 'package:fluro/fluro.dart';
class Application {
static Router router;
}
官方示例代码:
https://github.com/theyakka/fluro/blob/master/example/lib/config/application.dart
2、新建一个类,在里面封装所有的 处理路由的逻辑程序 handler
官方示例代码:
https://github.com/theyakka/fluro/blob/master/example/lib/config/route_handlers.dart
3、新建一个类,在里面封装所有的 定义路由 ,该类名字为 Routes 的类,该类里面因为会使用上一步的 handler,所以需要引入上一步的 handler 的类到此文件内
官方示例代码:
https://github.com/theyakka/fluro/blob/master/example/lib/config/routes.dart
这里面还配置了 找不到路由时的处理,就是那个 router.notFoundHandler
4、项目里使用时,只需引入 第1步和第3步 定义的2个类即可。然后就是实例化 router 并使用了:
final router = Router();
Routes.configureRoutes(router); //configureRoutes 是我们自定义的一个static 方法,用来结合 定义路由和路由处理逻辑的handler
Application.router = router; //Application 的 router 是static
最后就是在 MaterialApp 组件内使用:
MaterialApp(
title: 'Fluro',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
onGenerateRoute: Application.router.generator, //使用 Fluro
);
现在,我们要在哪里用路由,就引入最初静态化的 Application 类即可:
import './routers/application.dart';
在需要执行路由跳转的地方撸上即可实现路由跳转,比如:
Application.router.navigateTo(context,"/users/1234");
PS:
1、如何回传值:《futter 技术入门与实战》第二版11.2节 示例代码如下:
Routes.router.navigateTo(
context, '${Routes.page2}?message=$json',//跳转路径
transition: TransitionType.inFromRight//过场效果
).then( (result) { //回传值
if (result != null) {
message = result;
}
}
);
在页面内进行跳转时,可以 .then,定义好 用于第二个页面跳转回来时接收数据的处理逻辑。为什么可以.then ,是因为 本文第一部分第5点贴的 navigateTo 的源码可以看到,navigateTo 返回的是 Future。
第二个页面使用 Navigator.pop() 方法来回传数据,
Navigator.pop() 方法,会从导航器堆栈上移除 Route 对象。也就是返回上一个路由,使用 Navigator.pop(context); 它还有第二个可选参数,该参数为页面关闭时返回给上一个页面的数据。
Navigator.pop(context, '来自第二个界面的数据')
2、路由跳转时的参数传递与参数逻辑处理
1)参数如何传递到新路由页面那边呢?
路由跳转时通过 路由url 来传
router.define("/users/:id", handler: usersHandler);
更多的路由传参的url定义,可以看官方示例代码:https://github.com/theyakka/fluro/blob/master/example/lib/config/routes.dart
handler 里面通过 params 来获取并处理,请看下面 handler 处理参数
2)如何处理接收到的上一个路由页面传递过来的数据呢?
通过官方 handler 示例就可以看出 参数的处理都是在这里进行,Handler 的 handlerFunc 参数内可以处理传递的参数:https://github.com/theyakka/fluro/blob/master/example/lib/config/route_handlers.dart
var demoRouteHandler = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
String message = params["message"]?.first; //处理参数
String colorHex = params["color_hex"]?.first;
String result = params["result"]?.first;
Color color = Color(0xFFFFFFFF);
if (colorHex != null && colorHex.length > 0) {
color = Color(ColorHelpers.fromHexString(colorHex));
}
return DemoSimpleComponent(message: message, color: color, result: result); //使用参数
});
想要打赏,请点击这里