在主入口文件main.dart中尽量是做到简洁,如图示例就相对复杂了:
其中,routes(map对象):是项目的各个页面路由配置
initialRoute:是项目的根路由,初始化的时候最先展示的页面
onGenerateRoute(RouteFactory类型函数):路由钩子,可以对某些指定的路由进行拦截,有时候不想改变页面结构,但是又想要求跳转到这个页面的时候可以用到,比如,页面设定了传参你进行跳转的时候。
onUnknownRoute(RouteFactory类型函数):在路由匹配不到的时候用到,一般都返回一个统一的错误页面或404页面
解决方式:
在项目的目录下新建route.dart
class MYRouter {
static final Map<String, WidgetBuilder> routes = {
MYHomePage.routeName: (ctx) =>MYHomePage(), // 记得在页面里面 声明静态变量 static const String routeName = "/";
MYAboutPage.routeName: (ctx) => MYAboutPage()// 声明静态变量 static const String routeName = "/about";
};
static final String initialRoute = MYHomePage.routeName;
static final RouteFactory generateRoute = (settings) {
if (settings.name == MYDetailPage.routeName) {
return MaterialPageRoute(
builder: (ctx) {
return MYDetailPage(settings.arguments);
}
);
}
return null;
};
static final RouteFactory unknownRoute = (settings) {
return MaterialPageRoute(
builder: (ctx) {
return MYUnknownPage();
}
);
};
}
抽离后在main.dart再使用的时候会简洁很多了:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue, splashColor: Colors.transparent),
routes: MYRouter.routes,
initialRoute: MYRouter.initialRoute,
onGenerateRoute: MYRouter.generateRoute,
onUnknownRoute: MYRouter.unknownRoute,
);
}
}
常见的跳转方法:
//第一种:普通
Future result = Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) {
return MYDetailPage("a home message");
}
));
可以在MYDetailPage调用_backToHome方法的时候Navigator.of(context).pop("a detail message");以便父组件(main.dart)接收到值
// 第二种:带参数
Navigator.of(context).pushNamed(MYAboutPage.routeName, arguments: "a home message");
下级页面接收参数(注意:接收参数位置的地方对应三种方法): final String message = ModalRoute.of(context).settings.arguments as String;
about.dart
import 'dart:async';
import 'package:flutter/material.dart';
class MYAboutPage extends StatefulWidget {
static const String routeName = "/about";
@override
_MYAboutPageState createState() => _MYAboutPageState();
}
class _MYAboutPageState extends State<MYAboutPage> {
@override
void initState() {
super.initState();
// 第二种:如果在initState拿参数可以采用
Future.delayed(Duration.zero, () {
final String message = ModalRoute.of(context).settings.arguments as String;
print(message);
});
// 第三种:如果在initState拿参数可以采用
Timer.run(() {
final String message = ModalRoute.of(context).settings.arguments as String;
print(message);
});
}
@override
Widget build(BuildContext context) {
// 第一种:通常是在这拿参数
final String message = ModalRoute.of(context).settings.arguments as String;
return Scaffold(
appBar: AppBar(
title: Text("关于页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(message),
RaisedButton(
child: Text("返回首页"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
),
),
);
}
}
说明:针对onGenerateRoute,因为假设页面是这样:
detail.dart
import 'package:flutter/material.dart';
class MYDetailPage extends StatelessWidget {
// 当前页面肯定是要接收参数_message的,是必须的参数,也可以用required修饰强调
static String routeName="/detail";
final String _message;
DetailPage(this._message);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("详情页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_message, style: TextStyle(fontSize: 20),),
ElevatedButton (
child: Text("回到首页"),
onPressed: () => _backToHome(context),
)
],
),
),
);
}
void _backToHome(BuildContext context) {
Navigator.of(context).pop("a detail message");
}
}
如果按照正常的pushName逻辑跳转方法的话:
_jumpToDetail(BuildContext context) {
final res = Navigator.of(context).pushNamed(DetailPage.routeName, arguments: "我是参数");
/* 如果 采用这种方式 那么路由的配置就应该变为
routes:{
HomePage.routeName:(ctx)=>HomePage(),
"/detail":(ctx)=>DetailPage() //现在这样肯定是报错,而这个页面是需要必传参数的,所以 也不能写死为"/detail":(ctx)=>DetailPage("123")
}
// 所以在不改变DetailPage页面结构的情况下 必须使用路由钩子函数onGenerateRoute
*/
所以在这种情况下就适合使用钩子函数.
网友评论