fluro路由简单配置
- 引入
fluro
库
pubspec.yaml
yml
dependencies:
# 路由管理
fluro: ^2.0.5
一、封装fluro路由
- 主要初始化路由表信息,以及找不到页面时默认返回404页面
lib/router/routes.dart
dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/pages/home/router/router_test_page.dart';
import 'package:planx_app/pages/index_page.dart';
import 'package:planx_app/widget/empty.dart';
class Routes {
static FluroRouter router = FluroRouter();
// 设置页面
// 页面信息
static String indexPage = "/";
// 路由测试页面
static String routerPage = "/routerTest";
// 初始化,配置路由表
static _initRouter() {
// 首页
router.define(indexPage,
handler: Handler(handlerFunc: (_, __) => const IndexPage()));
// 路由测试页面
router.define(routerPage,
handler: Handler(handlerFunc: (_, __) => const RouterTestPage()));
}
// 配置路由
static void configureRoutes() {
router.notFoundHandler = Handler(handlerFunc: (_, __) {
// 找不到路由时,返回404页面
return Scaffold(
appBar: AppBar(),
// 这是自行封装的Empty组件
body: const Center(child: Empty(type: EmptyType.page404)));
});
// 初始化路由信息
_initRouter();
}
}
main.dart 中初始化与配置路由
dart
import 'package:planx_app/router/routes.dart';
void main() async {
// ...
// 注册路由
Routes.configureRoutes();
runApp(const MyApp());
}
// ....
// MaterialApp中配置路由
MaterialApp(
// ...
// 配置路由
onGenerateRoute: Routes.router.generator,
);
二、封装页面跳转的方法
- flutter中可以直接使用Navigator进行路由调整,为了统一建议还是先封装一下
- 这里只是简单的封装,在后面还有介绍关于无context跳转,以及特殊参数传递的封装
lib/router/navigator_util.dart
dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';
class NavigatorUtil {
static void push(
BuildContext context,
String path, {
bool replace = false, // 替换当前页面
bool clearStack = false, // 是否清空路由栈
Object? arguments,
TransitionType? transition, // 页面进入动效
}) {
Routes.router.navigateTo(
context,
path,
replace: replace,
clearStack: clearStack,
// 页面进入从右侧进入
transition: transition ?? TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
}
使用
dart
ElevatedButton(
onPressed: () {
NavigatorUtil.push(context, Routes.routerPage);
},
child: const Text("跳转路由测试页面"),
),
效果:
无context跳转
有些时候我们可能不会在builder中跳转路由,所以没有context
- 在MaterialApp中有一个navigatorKey属性,指定navigatorKey后就可以直接操作Navigator,不需要使用context
重新封装路由跳转方法
lib/router/navigator_util.dart
dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';
// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
class NavigatorUtil {
// 无context跳转
static void push(
String path, {
bool replace = false,
bool clearStack = false,
Object? arguments,
TransitionType? transition,
}) {
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: transition ?? TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context replase
static void replase(String path,
{bool replace = true, bool clearStack = false, Object? arguments}) {
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context,清空路由栈跳转,一般用于跳转首页这种情况
static void switchTab(String path,
{bool replace = false, bool clearStack = true, Object? arguments}) {
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
static void back({int count = 1, Object? params}) {
NavigatorState state = Navigator.of(navigatorKey.currentContext!);
while (count-- > 0) {
state = state..pop(params);
}
}
}
main.dart 配置
dart
import 'package:planx_app/router/navigator_util.dart';
import 'package:planx_app/router/routes.dart';
// ...
MaterialApp(
// ...
// 配置路由
onGenerateRoute: Routes.router.generator,
// 指定路由的全局key
navigatorKey: navigatorKey,
);
使用
dart
NavigatorUtil.push(Routes.routerPage);
传递参数
一、传递params参数
- 新建路由接收参数页面
router_params_page.dart
dart
class RouterParamsPage extends StatelessWidget {
const RouterParamsPage({Key? key, required this.content}) : super(key: key);
// 用来接收路由传递过来的参数
final String content;
@override
Widget build(BuildContext context) {
return Scaffold(
//....
body: Center(
child: Text(content), // 将参数显示到页面
),
);
}
}
- 配置路由
lib/router/routes.dart
dart
class Routes {
//...
// 路由传递参数页面
static String routerParamPage = "/routerParam";
static _initRouter() {
// ...
// 路由传递参数页面
router.define(routerParamPage,
handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
// 获取路由参数
String routerParam = params["content"]?[0];
return RouterParamsPage(content: routerParam);
}));
}
// ...
}
使用:路由跳转
- 相当于直接在url后面拼接参数
dart
// 传递参数
NavigatorUtil.push('${Routes.routerParamPage}?content=params11111');
参数带有特殊字符和中文时无法接收(比如: "www.baidu.com")
- 这种情况需要考虑进行encode这样保证参数正常
- 且通过上述的方法传递参数,每次都要拼接,并不优雅,我们顺便进行改造一下
改造NavigatorUtil方法,加密参数
- 以下封装是完整版本
lib/router/navigator_util.dart 加密
dart
import 'dart:convert';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';
// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
class NavigatorUtil {
// 这里进行加密
// 处理url参数拼接
static String _getPathParams({Map<String, String>? params, path}) {
if (params != null) {
// Utf8Encoder,解决参数有特殊字符,中文不能传递的情况
String p = params.entries
.map((e) =>
'${e.key}=${jsonEncode(const Utf8Encoder().convert(e.value))}')
.join('&');
path = '$path?$p';
}
return path;
}
// 无context跳转
static void push(
String path, {
Map<String, String>? params,
bool replace = false,
bool clearStack = false,
Object? arguments,
TransitionType? transition,
}) {
// 拼接params参数
path = _getPathParams(params: params, path: path);
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: transition ?? TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context replase
static void replase(
String path, {
Map<String, String>? params,
bool replace = true,
bool clearStack = false,
Object? arguments,
}) {
// 拼接params参数
path = _getPathParams(params: params, path: path);
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context,清空路由栈跳转,一般用于跳转首页这种情况
static void switchTab(
String path, {
Map<String, String>? params,
bool replace = false,
bool clearStack = true,
Object? arguments,
}) {
// 拼接params参数
path = _getPathParams(params: params, path: path);
Routes.router.navigateTo(
navigatorKey.currentContext!,
path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.inFromRight,
// routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
// 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
static void back({int count = 1, Object? arguments}) {
NavigatorState state = Navigator.of(navigatorKey.currentContext!);
while (count-- > 0) {
state = state..pop(arguments);
}
}
}
解码
- 在路由定义位置解码
lib/router/routes.dart
dart
// 路由传递参数页面
router.define(routerParamPage,
handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
// 获取路由参数
String routerParam = _decodeParams(params["content"]?[0]);
return RouterParamsPage(content: routerParam);
}));
//...
///字符串解码,中文不能传递等问题
static _decodeParams(String params) {
List<int> list = [];
jsonDecode(params).forEach(list.add);
return const Utf8Decoder().convert(list);
}
使用:
dart
// 传递参数
NavigatorUtil.push(Routes.routerParamPage, params: {"content": "https://www.bd的收费吗,是打开就好aidu.com"});
二、传递类实例参数
- 使用上面的NavigatorUtil方法,我们已经可以传递类参数了
使用页面:
dart
// 传递参数,arguments可以接收一个类作为参数,Person是自己定义的类
NavigatorUtil.push(Routes.routerInstancePage,arguments: Person(name: "terry", age: 40));
接收,需要在build中接收
dart
Widget build(BuildContext context) {
// 接收参数
Person p = (ModalRoute.of(context)?.settings.arguments as Person);
return Scaffold(
appBar: AppBar(title: Text('路由传递类参数')),
body: Center(
child: Column(
children: [
Text('ddd'),
Text('姓名${p.name}'),
Text('年龄${p.age}'),
],
)),
);
}