01
背景与动机
在Navigator 2.0推出之前,Flutter主要通过Navigator 1.0和其提供的 API(如push(), pop(), pushNamed()等)来管理页面路由。然而,Navigator 1.0存在一些局限性,如难以实现复杂的页面操作(如移除栈内中间页面、交换页面等)、不支持嵌套路由以及无法满足全平台(尤其是Web平台)的新需求。因此,Flutter官方团队决定对路由系统进行改造,推出了Navigator 2.0。
02
主要特性
声明式API
Navigator 2.0提供的声明式API使得路由管理更加直观和易于理解。开发者只需声明页面的配置信息,而无需编写复杂的导航逻辑代码。这种方式不仅减少了代码量,还提高了代码的可读性和可维护性。嵌套路由
Navigator 2.0满足了嵌套路由的需求场景,允许开发者在应用中创建嵌套的路由结构。这使得应用的结构更加清晰,同时也提高了页面导航的灵活性。全平台支持
Navigator 2.0提供的API能够满足不同平台(如iOS、Android、Web等)的导航需求,使得开发者能够更加方便地构建跨平台的应用。强大的页面操作能力
Navigator 2.0提供了更加丰富的页面操作能力,如移除栈内中间页面、交换页面等。这些操作在Navigator 1.0中很难实现或需要编写复杂的代码,而在Navigator 2.0中则变得简单直接。
03
核心组件
Router 在
Navigator 2.0中,Router组件是路由管理的核心。它负责根据当前的路由信息(RouteInformation)和路由信息解析器(RouteInformationParser)来构建和更新UI。Router组件接收三个主要参数:1.routeInformationProvider:提供当前的路由信息;
2.routeInformationParser:将路由信息解析为路由配置;
3.routerDelegate:根据路由配置构建和更新
UI。RouteInformationProvider
RouteInformationProvider是一个提供当前路由信息的组件。它通常与平台相关的路由信息源(如浏览器的URL、Android的Intent等)集成,以获取当前的路由信息。RouteInformationParser
RouteInformationParser负责将RouteInformation解析为RouteConfiguration。这个过程允许开发者根据路由信息的格式(如URL)来定义如何将其映射到应用内的路由配置。RouterDelegate
RouterDelegate是与UI构建紧密相关的组件。它必须实现RouterDelegate接口,并提供两个主要方法:1.build(BuildContext context):根据当前的路由配置构建
UI;2.setNewRoutePath(List configuration):设置新的路由路径,并更新
UI;3.Future popRoute() :实现后退逻辑。
04
简单实例
首先通过MaterialApp.router()来创建MaterialApp:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final routerDelegate = MyRouterDelegate();
final routeInformationParser = MyRouteInformationParser();
return MaterialApp.router(
title: 'Flutter Navigator 2.0 Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routerDelegate: routerDelegate,
routeInformationParser: routeInformationParser,
);
}
}
需要定义一个RouterDelegate对象和一个RouteInformationParser对象。其中根据路由配置构建和更新UI,RouteInformationParser负责将RouteInformation解析为RouteConfiguration。 RouterDelegate可以传个泛型,定义其currentConfiguration对象的类型。
class MyRouterDelegate extends RouterDelegate<String>
with PopNavigatorRouterDelegateMixin<String>, ChangeNotifier {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
private List<String> _pages = ['/home'];
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: _pages.map((route) => MaterialPage(
key: Key(route),
child: generatePage(route),
)).toList(),
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
_pages.removeLast();
notifyListeners();
return true;
},
);
}
@override
Future<void> setNewRoutePath(String path) async {
if (!_pages.contains(path)) {
_pages.add(path);
notifyListeners();
}
}
Widget generatePage(String route) {
switch (route) {
case '/home':
return HomePage();
case '/details':
// 这里可以传递参数,例如 DetailsPage(arguments: someData)
return DetailsPage();
default:
return NotFoundPage();
}
}
@override
String get currentConfiguration => _pages.last;
}
其中build()一般返回的是一个Navigator对象,popRoute()实现后退逻辑,setNewRoutePath()实现新页面的逻辑。定义了一个_pages数组对象,记录每个路由的path,可以理解为是一个路由栈,这个路由栈对我们来说非常友好,在有复杂的业务逻辑时,我们可以自行定义相应的栈管理逻辑。currentConfiguration返回的是栈顶的page信息。创建一个类继承RouteInformationParser,主要的作用是包装解析路由信息,这里有一个最简单的方式,如下:
class MyRouteInformationParser extends RouteInformationParser<String> {
@override
Future<String> parseRouteInformation(RouteInformation routeInformation) {
final uri = Uri.parse(routeInformation.location);
return SynchronousFuture(uri.path);
}
@override
RouteInformation restoreRouteInformation(String configuration) {
return RouteInformation(location: configuration);
}
}
好的,接下来我们看一下调用:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
onPressed:&

最低0.47元/天 解锁文章
821

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



