配置
需要在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
至此,命名路由管路指北结束,撒花✿✿✿✿ヽ(°▽°)ノ✿✿✿✿
本文深入讲解Flutter中命名路由的配置与使用,包括参数传递、返回与回调机制,以及解决Navigator.xxxUntil方法中路由路径信息缺失的问题。
967

被折叠的 条评论
为什么被折叠?



