路由管理
路由的概念在应用程序中可以理解为页面之间的跳转逻辑,在Android中指的是Activity之间的跳转,在IOS中指的是View之间的跳转。Flutter也有自己的路由,Flutter中的路由指的是Widget的跳转。Flutter中路由分为动态路由和静态路由
3.1.1 动态路由
路由跳转是指的页面之间通过指定配置相互跳转,比如页面A跳转到页面B,然后页面B再返回到页面A等类似的操作。
//第一个页面
class PageOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('第一个页面'),
centerTitle: true,
),
body: Center(
child: RaisedButton(
child: Text('跳到第二个页面'),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return PageTwo();
}));
}),
),
);
}
}
//第二个页面
class PageTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('第二个页面'),
centerTitle: true,
),
body: Center(
child: RaisedButton(
child: Text('返回'),
onPressed: () {
Navigator.of(context).pop();
}),
),
);
}
在这个示例中定义了两个页面PageOne和PageTwo,两个页面各有一个按钮,PageOne页面点击 跳到第二个页面 按钮时会跳转到PageTwo页面,当点击PageTwo页面的 返回 按钮时会返回到PageOne页面。这个示例中有几个需要关注的点:
1. Navigator
Navigator就是Flutter的路由控制器,通过栈的方式来管理路由,主要用于控制路由的进入和退出。
Navigator提供了一些方法来管理路由,上面的例子使用了两个最基本的方法,push和pop,实现了基本的页面进入和退出的操作。
push()
进入操作,路由进栈,并且位于栈顶。接收一个MaterialPageRoute作为参数。
pop()
退出操作,路由出栈,不接收任何参数,返回上一个页面。
2. MaterialPageRoute
MaterialPageRoute是Material风格的路由组件,在Android中表现为页面从下到上滑入,从上到下滑出。在IOS中表现为页面从左到右滑入,从右到左滑出。
MaterialPageRoute的参数构成:
MaterialPageRoute({
@required this.builder,
RouteSettings settings,
this.maintainState = true,
bool fullscreenDialog = false,
})
- builder 必填 WidgeBuilder类型的回调参数,作用是构建路由页面的具体内容,返回一个widget,需要实现这个回调来创建路由实例。
- settings 路由相关信息设置,路由名称、是否初始路由等。
- maintainState 默认true,启动一个新的路由时,原来的路由资源依然保存在内存中,需要释放路由资源时可以将属性值设置为false。
- fullscreenDialog 默认false,新的路由页面是否以全屏对话框模式展示。
3.1.2 静态路由
上面例子中,PageOne跳转到PageTwo的时候MaterialPageRoute返回的是PageTwo的实例,这种方式属于动态路由,优点是在前一个页面直接指定将要跳转的页面,简单明了,适合少量页面跳转。缺点是当程序页面比较多的时候不利于路由的统一管理。为了统一管理路由,Flutter也提供了另一种路由实现方式:静态路由(也叫做命名路由)
命名路由就是给路由起一个名字,通过这个名字打开新的页面。要使用命名路由需要以下几个步骤:
1.创建路由表
//路由表
class Routes {
static const String onePage = 'one_page';
static const String twoPage = 'two_page';
//路由映射关系
static Map<String, WidgetBuilder> routes = {
onePage: (context) => PageOne(),
twoPage: (context) => PageTwo(),
};
}
2.注册路由表
return MaterialApp(
title: 'flutter demo',
theme: ThemeData(
primaryColor: Colors.blue,
),
home: PageOne(),
//注册路由表(使用命名路由时需要注册路由表)
routes: Routes.routes,
);
3.打开页面
在点击事件中使用命名路由跳转
onPressed: () {
// 使用命名路由跳转
Navigator.of(context).pushNamed(Routes.twoPage);
}),
3.1.3 路由传值
还是以上面的两个页面为例,假如在从PageOne跳转到PageTwo的时候需要携带一个字符串作为参数传递给PageTwo,并且PageTwo在点击返回按钮的时候也需要回传一个参数给PageOne。这种情况下就需要使用路由传值了。因为路由本身分为动态路由和静态路由,所以不同路由的参数传递和接收的形式也是不同的,下面就以上文中的PageOne和PageTwo两个页面为例,说明一下两种路由方式传参的方式和区别
1. 动态路由传参
动态路由传参的使用方式主要有一下几个步骤:
1. 传递参数
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return PageTwo(mtext: "10");
}))
2. 定义并且初始化变量
final String mtext;
// mtext的值就是上一个页面传递过来的值
PageTwo({this.mtext});
// PageTwo({Key key, this.mtext}) : super(key: key);
3. 使用参数
Text('$mtext'),
动态路由接收返回值:
1. 首先再PageTwo页面点击返回按钮的时候添加返回参数
RaisedButton(
child: Text('返回'),
onPressed: () {
//在pop中将数据返回给第一个页面
Navigator.of(context).pop("返回了");
})
2. PageOne页面中接收返回值,两种写法
// 1.Future.then()链式回调方式
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return PageTwo(mtext: "10");
})).then((value) => print(value));
// 2. async/awatit异步方式
onPressed: () async{
var result = await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return PageTwo(
mtext: "10",
);
}));
print(result);
})
// 这两种方式都可以达到效果,关于Future.then()链式回调和async/awatit会在dart基础部分介绍。
2. 静态路由传参
静态路由传参需要经过一下几个步骤:
1. 创建路由表
2. 注册路由表
//如何创建和注册路由表,上文已经有介绍
3. 传递参数
RaisedButton(
child: Text('静态路由传参'),
onPressed: () {
Navigator.of(context).pushNamed(Routers.page_three, arguments: "hello");
})
//arguments可以是任何dart类型,传参的时候是什么类型的数据,后续页面就要用对应的类型来接收,比如示例用传递的是字符串,后面接收的时候就需要用字符串接收
4. 接收参数
var arg = ModalRoute.of(context).settings.arguments;
//这里需要注意arguments的类型
5. 使用参数
Text('$arg')
静态路由接收返回值的方式同动态路由