本文中涉及部分非Flutter的stable
版本(2019年2月25日 为止)
,您可查阅Flutter相关文档查看新功能是否同步的stable
分支或者切换其他分支(如master
)中体验
引言
在我们使用Flutter开发App时,路由是必须用到的。
Flutter提供了两种方式进行路由,分别是 Navigator.push()
(例) 以及 Navigator.pushNamed()
(例)。
对于这两种方式各有各的优点与缺点:
- Navigator.push()
- 优点:动态、自由度大,可以以不同的动画方式跳转到新页面,且可以传递参数到新的页面。
- 缺点:会造成代码冗余,而且不便于代码维护。(当然你可以将其进行封装 这里不讨论这一点)
- Navigator.pushNamed()
- 优点:一句话就能实现页面的跳转与目前大多数框架的方式相似。
- 缺点:不能传递参数!不能传递参数!不能传递参数!
选择
在实际开发运用中,我们也是更加倾向于Named
路由方式。
但是唯一不足之处就是它不支持传递参数,这一点实在是令人抓狂。
其实在Flutter的Issues中16年就有人提出这个问题,但是这个Issue一直到今年才有PR被提交(目前为止这个功能仅仅被合并进master分支并没有同步到bate或者stable)
上手体验
- 首先我们要切到master分支下
执行
flutter channel master
然后再运行命令flutter upgrade
保证你处于最新的版本。即可切换到master分支下
- 创建一个Flutter项目
- 这里我们在
main.dart
中略作修改
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Center(
child: GestureDetector(
onTap: (){
// TODO
},
child: Text("go next page with params"),
),
),
);
}
}
复制代码
- 添加第二个页面
page.dart
import 'package:flutter/material.dart';
class Page extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Text("hi this is next page"),
),
);
}
}
复制代码
- 添加路由并跳转同时传递参数
main.dart
import 'package:flutter/material.dart';
// 引入新页面
import 'page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// 处理Named页面跳转 传递参数
onGenerateRoute: (RouteSettings setting) {
if(setting.name == '/page') {
return MaterialPageRoute(builder: (context) => Page(id: setting.arguments['id']));
}
},
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Center(
child: GestureDetector(
onTap: (){
// 进行Named页面跳转 传递参数
Navigator.pushNamed(context, '/page', arguments: { "id": 1} );
},
child: Text("go next page with params"),
),
),
);
}
}
复制代码
- 页面接受参数
page.dart
import 'package:flutter/material.dart';
class Page extends StatelessWidget{
Page({this.id});
final int id;
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Text("hi this is next page, id is $id"),
),
);
}
}
复制代码
效果
优化
这里我们还是要在onGenerateRoute
处理我们的Named跳转,我们在对他进行优化一下。
(目前没办法在MaterialApp的routes进行处理,原因可见源码(一)(二))
源码一处:调用
widget.pageRouteBuilder
并传入settings
(arguments
在settings
中)源码二处:
pageRouteBuilder
被写死为构建一个MaterialPageRoute
,而MaterialPageRoute
中并没有对settings
进行传递所以我们只能自己在
onGenerateRoute
中进行处理。(希望官网也能继续优化,emmmm拭目以待)
/**
* main.dart
*/
import 'package:flutter/material.dart';
// 引入新页面
import 'page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// 定义路由信息
final Map<String, Function> routes = {
'/page': (context, {arguments}) => Page(arguments: arguments)
};
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// 处理Named页面跳转 传递参数
onGenerateRoute: (RouteSettings settings) {
// 统一处理
final String name = settings.name;
final Function pageContentBuilder = this.routes[name];
if (pageContentBuilder != null) {
final Route route = MaterialPageRoute(
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
}
},
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Center(
child: GestureDetector(
onTap: () {
// 进行Named页面跳转 传递参数
Navigator.pushNamed(context, '/page', arguments: {'id': 123});
},
child: Text("go next page with params"),
),
),
);
}
}
/**
* page.dart
*/
import 'package:flutter/material.dart';
class Page extends StatelessWidget{
Page({this.arguments});
final Map arguments;
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Text("hi this is next page, id is ${arguments != null ? arguments['id'] : '0'}"),
),
);
}
}
复制代码
相关代码
flutter_new_feature