配置
需要在main.dart
文件的第一个MaterialApp中配置命名路由信息:
import 'package:iting/constant/route_config.dart';
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
///默认不显示debug
debugShowCheckedModeBanner: false,
theme: ThemeData(primaryColor: Colors.orange),
///命名路由表
routes: namedRoutes,
///注入路由表,当路由没有在命名路由表中注册时调用
onGenerateRoute: onGenerateRoute,
///404
onUnknownRoute: onUnknownRoute,
///具体页面
home: Scaffold(
resizeToAvoidBottomPadding: false,
body: ...,
),
);
}
}
这里是通过引入外部命名路由文件route_config.dart
进行路由信息的配置,当然也可以在对应参数后面直接配置对应类型的数据
route_config.dart
配置文件:
import 'package:flutter/material.dart';
import '../404notfound.dart';
final Map<String, WidgetBuilder> namedRoutes = {
PageA.pageName: (ctx) => PageA(),
};
final Route<dynamic> Function(RouteSettings settings) onGenerateRoute =
(settings) {
WidgetBuilder builder;
if (settings.name == PageB.pageName) {
builder = (context) => PageB(page_b_id: settings.arguments);
}
return MaterialPageRoute(
builder: (context) {
return builder(context);
},
);
};
final Route<dynamic> Function(RouteSettings settings) onUnknownRoute =
(settings) {
return MaterialPageRoute(
builder: (context) {
return NotFoundPage();
},
);
};
PageA.dart
class PageA extends StatefulWidget {
static final String pageName = "PageA";
@override
_PageAState createState() => _PageAState();
}
class _PageAState extends State<PageA> {
var value = ModalRoute.of(context).settings.arguments;
@override
Widget build(BuildContext context) {
return Container(
...
);
}
}
PageB.dart
class PageB extends StatefulWidget {
static final String pageName = "PageB";
PageB({int page_b_id});
@override
_PageBState createState() => _PageBState();
}
class _PageBState extends State<PageB> {
@override
Widget build(BuildContext context) {
return Container(
...
);
}
}
参数
routes:命名路由表,返回Map<String, WidgetBuilder>
类型的数据,通过命名路由跳转界面时会首先从这个Map中寻找对应的页面,如果找到则进行跳转
onGenerateRoute:路由拦截表,返回一方法,方法以RouteSettings
为参数,Route<dynamic>
为返回值,再routes中没有查询到的路由会进入这里面进行查询匹配
onUnknownRoute:如果上面查询都失败了,则会调用此方法,可以这里处理返回信息,我在这里是返回一个404的页面
使用与传参
配置了这些信息,就可以:
- 通过
Navigator.of(context).pushNamed(PageA.pageName);
跳转到PageA - 通过
Navigator.of(context).pushNamed(PageB.pageName,arguments: 123);
跳转到PageB,并在onGenerateRoute
匹配路由名称,用setting
获取路由信息,并通过构造函数传参 - 通过
Navigator.of(context).pushNamed(PageA.pageName,arguments: 123);
跳转到PageA,通过无构造函数传参,在目标页面,通过ModalRoute.of(context).settings
,在build方法中获取路由信息和对应参数。
无构造传参的方式在StatefulWidget
中的initState
生命周期方法中调用ModalRoute.of(context)
会报错,原因是context
尚未初始化完成不能使用,直到state
相关framework
关联完成才可以使用;如果需要初始化时就要使用,则可以通过构造函数传参,并通过widget
传递给state
返回与回调
通常我们使用Navigator
的pop
方法进行路由的回退
Navigator.of(context).pop();
Navigator
的方法中所有带push
的方法会返回带泛型的Future
同理,Navigator
的pop
,maybePop
,popAndPushNamed
方法参数中会携带一个参数
路由传参回调主要是通过就是通过这两者结合起来的
跳转:
Navigator.of(context)
.pushNamed(routerName, arguments: arguments)
.then((value) {
print("value ${value}");
});
返回:
Navigator.of(context).pop(true);
注意
通过上面的配置确实已经可以完成命名路由的配置和使用
但是在诸如Navigator.xxxxUntil
的路由方法中,通过RoutePredicate
参数打印已经经历过的路由路径信息时会发现,那些没有在routes
中配置,直接通过onGenerateRoute
中匹配的路由路径返回的信息是null
,这样就导致了Navigator.xxxxUntil
方法使用的局限性,你会找不到停靠的目标页面
为了解决这一问题,上述的onGenerateRoute
中需要做如下修改:
final Route<dynamic> Function(RouteSettings settings) onGenerateRoute =
(settings) {
WidgetBuilder builder;
if (settings.name == PageB.pageName) {
builder = (context) => PageB(page_b_id: settings.arguments);
}
return MaterialPageRoute(
settings: RouteSettings(
name: settings.name,
arguments: settings.arguments,
),
builder: (context) {
return builder(context);
},
);
};
在返回MaterialPageRoute
时,通过setting
参数传入路由信息RouteSettings
至此,命名路由管路指北结束,撒花✿✿✿✿ヽ(°▽°)ノ✿✿✿✿