Flutter之路由管理
1.MaterialPageRoute
MaterialPageRoute继承自PageRoute类,PageRoute类是一个抽象类,表示占有整个屏幕空间的一个模态路由页面,它还定义了路由构建及切换时过渡动画的相关接口及属性。MaterialPageRoute 是Material组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画:
关于MarterialPageRoute的构造器参数:
MaterialPageRoute({
WidgetBuilder builder,
RouteSettings settings,
bool maintainState = true,
bool fullscreenDialog = false,
})
- builder : 是一个WidgetBuilder的回调函数,返回值是Widget,返回的是一个新路由的实例.
- settings :包含路由的配置信息,如路由名称、是否初始路由(首页)。
class RouteSettings {
/// Creates data used to construct routes.
const RouteSettings({
this.name,
this.isInitialRoute = false,
this.arguments,
});
- maintainState : 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false
- fullscreenDialog : 表示新的路由页面是否是一个全屏的模态对话框,在iOS中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)相当于IOS中的present()方法跳转界面。
如果想自定义路由切换动画,可以自己继承PageRoute来实现.
Navigator
Navigator:是一个管理路由的组件,通过一个栈来管理活动路由集合(相当于IOS中的导航控制器)
Future push(BuildContext context, Route route)
将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据。
bool pop(BuildContext context, [ result ])
将栈顶路由出栈,result为页面关闭时返回给上一个页面的数据。
实例方法
Navigator类中第一个参数为context的静态方法都对应一个Navigator的实例方法, 比如Navigator.push(BuildContext context, Route route) 等价于Navigator.of(context).push(Route route)
命名路由
要使用命名路由,我们首先要注册一个路由表
Map<String, WidgetBuilder> routes;
类似这种定义:
Map<String, WidgetBuilder> routes = {
'Controller demo': (BuildContext context){ return ControllerDemoPage(title: 'Controller demo');},//没有省略的写法
'Clip demo' : (BuildContext context) => ClipDemoPage(title: 'Clip demo'),//省略写法
'Scroll demo' : (BuildContext context) => ScrollListenerDemoPage(title: 'Scroll demo'),
'ScolllToIndex demo' : (context) => ScrollToIndexDemoPage(title: '列表滑动到制定位置'),
'Refresh demo' : (context) => RefreshDemoPage(),
};
跳转时可以这样写:
Navigator.push(context, MaterialPageRoute(
builder: routes[routeNames[index]],
));
也可以直接在MaterialApp的属性中直接声明:
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context)=>NewRoute(),
... // 省略其它路由注册信息
} ,
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
如果我们想把home: 属性后面的 路由也注册在表中,可以这样设置
MaterialApp(
title: 'Flutter Demo',
initialRoute:"/", //名为"/"的路由作为应用的home(首页)
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context)=>NewRoute(),
"/":(context)=> MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
}
);
通过路由名打开新路由
Future pushNamed(BuildContext context, String routeName,{Object arguments})
除此之外API中还有许多其他的方法,请查看API详细了解
简单实现电商app的权限控制
假设我们要开发一个电商APP,当用户没有登录时可以看店铺、商品等信息,但交易记录、购物车、用户个人信息等页面需要登录后才能看。为了实现上述功能,我们需要在打开每一个路由页前判断用户登录状态!如果每次打开路由前我们都需要去判断一下将会非常麻烦,那有什么更好的办法吗?答案是有!
MaterialApp有一个onGenerateRoute属性,它在打开命名路由时可能会被调用,之所以说可能,是因为当调用Navigator.pushNamed(…)打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果路由表中没有注册,才会调用onGenerateRoute来生成路由。onGenerateRoute回调签名如下:
Route Function(RouteSettings settings
有了onGenerateRoute回调,要实现上面控制页面权限的功能就非常容易:我们放弃使用路由表,取而代之的是提供一个onGenerateRoute回调,然后在该回调中进行统一的权限控制,如:
MaterialApp(
... //省略无关代码
onGenerateRoute:(RouteSettings settings){
return MaterialPageRoute(builder: (context){
String routeName = settings.name;
// 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
// 引导用户登录;其它情况则正常打开路由。
}
);
}
);
注意,onGenerateRoute只会对命名路由生效,也就是Navigator.pushName()。
本文参考链接 :https://book.flutterchina.club/chapter2/flutter_router.html