Linuxword Global
当前位置: 软件下载 > 全网最简单的Flutter Navigator2.0路由指南

1c06ec8e1ea8431585de46d09d4b8691tplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

关于Flutter路由的一些原理,可以阅读我们之前的文章《Flutter 路由源码剖析》,本文我们主要来学习一下Navigator2.0的用法。
为了演示Navigator2.0的用法,这里准备了一个简单案例,项目下载 访问这里。
nav_demo目录是一个使用Navigator1.0的示例,总共4个页面,分别是:splash、login、home、details代码结构如下:

7417f173824640d0ba73d21f10b02590tplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

核心代码:

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigator 1.0',
routes: <String, WidgetBuilder> {
'/login': (_) => const Login(),
'/home': (_) => const Home(),
},
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Splash(),
);
}
}

Navigator1.0 存在的几个问题:

静态路由不方便给构造函数传参,不如动态路由灵活。如不考虑使用第三方路由框架时,常常会存在静态路由和动态路由一起使用的情况。如下代码,点击网格项,拉起详情页
GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(
builder: (ctx) => Details(
_movieList![i].name, _movieList![i].imgUrl)));
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(child: Image.network(_movieList![i].imgUrl)),
Text(_movieList![i].name),
],
),
);
难以处理Web版上,地址栏URL做路由导航的需求。如下图,切换路由,地址栏没有变化

对路由的控制极不灵活,譬如对路由嵌套的场景需求;处理Android返回键需求等
编程风格不统一。Navigator 1.0是一种命令式编程范式,而Flutter本身是一种声明式的编程范式。Navigator 2.0回归声明式的范式,更具Flutter的味道。
使用Navigator 2.0重构
这里,我先以一种最少的修改,最简单的使用方式来重构,看看Navigator 2.0是如果使用的
修改代码结构:

ca58bae639244cb29abda0174fbacc79tplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

仅添加router文件夹,新增delegate.dart文件。在其中自定义类MyRouterDelegate继承自RouterDelegate,并混入ChangeNotifier和PopNavigatorRouterDelegateMixin。
这里有三个方法必须实现:

class MyRouterDelegate extends RouterDelegate<List<RouteSettings>> with ChangeNotifier, PopNavigatorRouterDelegateMixin<List<RouteSettings>> {

final List<Page> _pages = [];

@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: List.of(_pages),
onPopPage: _onPopPage,
);
}

@override
Future<void> setNewRoutePath(List<RouteSettings> configuration) async {}

/// ………………省略部分代码………………
}

setNewRoutePath方法可以先留空,主要看一下build方法。我们创建了Navigator作为路由的管理者,并设置了两个主要参数pagesonPopPage,其中pages是一个存放Page对象的列表;当路由被pop时,onPopPage会被回调,开发者可在此处理路由退栈的逻辑。

这里,我们真正需要关心的是,Page对象列表是什么东西?

我们知道,在Flutter中,使用路由这个词来表示App中的页面,路由栈也就是页面栈。2.0提出的这个Page类,实际上就相当于是一个路由的描述文件。这个思想就类似于我在《Flutter 框架实现原理》一文提到的Flutter的四颗树。Flutter中的所谓Widget就是一种配置描述,而Element类就根据这个描述生成的。同理,Page也是一种描述,用于生成真正的路由对象。

2f5643234e344690bfc15bd3dea7e739tplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

理解了这一点,你就会明白,Navigator2.0不仅没有让路由管理更复杂,反而更简单了。我们只要操作这个Page列表,相应的路由栈就会感知到,自动发生变化。我们想要哪个页面显示,只需要把它放置到List的最后一个元素位置即可。Navigator2.0就是把原来对形同黑盒子的路由栈操作变成了一个对列表List的操作。我们想要改变路由栈中页面的先后顺序,只需要修改List<Page>中的元素位置。

846e809b921345b29a7d5c8e87d280a5tplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

接下来就需要看一下,如何使用Page类创建对象。Page类本身继承自RouteSettings类,这说明它确实就是一个路由配置文件。它本身是一个抽象类,不能实例化,我们找到了它的两个直接实现类:

32aaadeb248f4362844e00f7797d03ectplv-k3u1fbpfcp-zoom-in-crop-mark1512000.awebp_

这里我们一看就明白了,Flutter已经给我们提供好了实现类,一个是Android的Material风格,一个是iOS的Cupertino风格。

直接使用MaterialPage包装我们写的页面,增加一个方法封装这些逻辑,帮助创建Page

MaterialPage _createPage(RouteSettings routeSettings) {
Widget child;

switch (routeSettings.name) {
case '/home':
child = const Home();
break;
case '/splash':
child = const Splash();
break;
case '/login':
child = const Login();
break;
case '/details':
child = Details(routeSettings.arguments! as Map<String, String>);
break;
default:
child = const Scaffold();
}

return MaterialPage(
child: child,
key: Key(routeSettings.name!) as LocalKey,
name: routeSettings.name,
arguments: routeSettings.arguments,
);
}

此处的处理,有些类似于静态路由配置表,但是注意到,我们可以通过RouteSettings 参数,给页面的构造方法传参了,比1.0的静态路由灵活许多。
好了,到这里就只需要写几个方法来操作Page列表:

 

「梦想一旦被付诸行动,就会变得神圣,如果觉得我的文章对您有用,请帮助本站成长」

赞(1) 打赏
一分也是爱

支付宝扫一扫打赏

微信扫一扫打赏

上一篇:

下一篇:

相关推荐

博客简介

本站CDN采用VmShell免费提供离中国大陆最近的香港CMI高速网络做支撑,ToToTel打造全球最快速的边沿网络支撑服务,具体详情请见 :https://vmshell.com/ 以及 https://tototel.com/,网站所有的文件和内容禁止大陆网站搬迁复制,谢谢,VPS营销投稿邮箱: admin@linuxxword.com,我们免费帮大家发布,不收取任何费用,请提供完整测试文稿!

精彩评论

友情链接

他们同样是一群网虫,却不是每天泡在网上游走在淘宝和网游之间、刷着本来就快要透支的信用卡。他们或许没有踏出国门一步,但同学却不局限在一国一校,而是遍及全球!申请交换友链

站点统计

  • 文章总数: 2342 篇
  • 草稿数目: 13 篇
  • 分类数目: 6 个
  • 独立页面: 0 个
  • 评论总数: 2 条
  • 链接总数: 0 个
  • 标签总数: 6121 个
  • 注册用户: 139 人
  • 访问总量: 8,693,139 次
  • 最近更新: 2024年4月30日