写点什么

【Flutter 专题】110 页面间小跳转 (四)

发布于: 2021 年 06 月 07 日
【Flutter 专题】110 页面间小跳转 (四)

      小菜计划针对页面间跳转的路由相关知识做一个汇总,发现有两类特殊方法暂未研究,今天特补充 Navigator 相关方法应用;

canPop

      小菜理解 Navigator 是对栈的操作,对于出栈的过程,可以通过 canPop 判断栈内 Page 是否存在,防止在栈内没有元素时强制 Pop 出栈引起异常;

源码解析

bool canPop() {    return _history.length > 1 || _history[0].willHandlePopInternally;}
复制代码

案例尝试

if (Navigator.of(context).canPop()) {  print('当前 ${ModalRoute.of(context).settings.name} 可以 Pop !');  Navigator.pop(context);} else {  print('当前 Page 无法 Pop ! ModalRoute.of(context).isFirst = ${ModalRoute.of(context).isFirst}');}
复制代码

maybePop

      canPop 只是对栈内元素是否可以出栈的判断,而 maybePop 不仅可以判断还可以执行 Pop 出栈操作;

源码解析

Future<bool> maybePop<T extends Object>([ T result ]) async {  final _RouteEntry lastEntry = _history.lastWhere(_RouteEntry.isPresentPredicate, orElse: () => null);  if (lastEntry == null)  return false;  final RoutePopDisposition disposition = await lastEntry.route.willPop(); // this is asynchronous  if (!mounted)    return true; // forget about this pop, we were disposed in the meantime  final _RouteEntry newLastEntry = _history.lastWhere(_RouteEntry.isPresentPredicate, orElse: () => null);  if (lastEntry != newLastEntry)    return true; // forget about this pop, something happened to our history in the meantime  switch (disposition) {    case RoutePopDisposition.bubble:      return false;    case RoutePopDisposition.pop:      pop(result);      return true;    case RoutePopDisposition.doNotPop:      return true;  }  return null;}
复制代码


      简单分析源码可得,maybePop 会有限判断当前路由栈在列表中是否为最后一个,如果是最后一个则不进行出栈操作,否则进行 Pop 出栈;小菜简单理解为 maybePop >= canPop + Pop

案例尝试

// 分别在 PageA 和 PageB 页面调用 maybePopNavigator.of(context).maybePop();
复制代码

MaterialApp

      我们每次新建一个工程,通常会采用 MaterialApp 作为 runApp() 的始点,MaterialAppAndroid 风格的,若需要 iOS 风格的,则需要 CupertinoApp;即作为整个应用风格 Widget;而 MaterialApp / CupertinoApp / WidgetApp 等小组件默认是内嵌 Navigator 的,小菜接下来介绍 MaterialApp 几个重要属性;

1. home

      当进入应用时,初始化展示的 Widget


class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(        title: 'Flutter Demo',        theme: ThemeData(primarySwatch: Colors.blue),        initialRoute: '/',        onGenerateRoute: generateRoute,        home: Scaffold(            appBar: AppBar(title: Text('HomePage')),            body: Center(child: Text('HomePage'))));  }}
复制代码



2. routes

      routes 为静态路由映射表,是 Map<String, WidgetBuilder> 类型,当使用类似于 pushNamed 静态路由方式进行页面跳转时,其对应路由首先需要在此绑定;一般默认 / 对应 root 页面,当然我们可以自定义为其他名称,只是系统规则一般是 /,其中 Navigator.defaultRouteName 对应的也是 /;其余的页面路由可以根据业务逻辑进行文件夹式的层级结构;小菜在 Android 原生开发时采用过 ARouter 插件,其方式基本类似;


      注意: 一般采用 home 方式展示 Widget 时,路由表中不设置 / 对应 root 路由;

3. initialRoute

      initialRoute 用于设置初始启动页面,一般设置后就无需设置 home 属性,因为 home 对应展示 Widget 优先级更高;若首页映射表名称采用 / 对应 root 路由时,可以省略 initialRoute 属性;


class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      theme: ThemeData(primarySwatch: Colors.blue),//        initialRoute: '/',      routes: { '/': (context) => HomePage(title: 'HomePage') },      onGenerateRoute: generateRoute,//      home: Scaffold(//          appBar: AppBar(title: Text('HomePage')),//          body: Center(child: Text('HomePage'))),    );  }}
复制代码


4. onGenerateRoute

      onGenerateRouteRouteFactory 类型构造函数,当使用静态路由进行页面跳转时,进入未在 routes 中绑定的页面时,都会在 onGenerateRoute 中进行回调;一般在封装时,不设置 routes 属性,均在 onGenerateRoute 中进行业务判断,常用作类似于拦截器的路由守卫等;同时对于公共的自定义路由专场动画也可以再此处理;


Function generateRoute = (settings) {  print('onGenerateRoute -> $settings');  if (settings == null ||      settings.name == null ||      routes[settings.name] == null) {    return MaterialPageRoute(builder: (context) => routes['/error']());  } else if (settings.arguments != null) {    return MaterialPageRoute(        builder: (context) => routes[settings.name](settings.arguments));  } else if (settings.name == '/') {    return MaterialPageRoute(        builder: (context) => routes[settings.name]('HomePage'));  } else {    return MaterialPageRoute(builder: (context) => routes[settings.name]());  }};
复制代码

5. onUnknownRoute

      onUnknownRoute 同样为 RouteFactory 类型构造函数,当使用静态路由进行页面跳转时,无法在 onGenerateRoute 中生成时进行回调;

6. builder

      builder 属性常用作 MediaQuery 设备信息获取或用户信息偏好设置等;小菜之前有整理过关于 MediaQuery 的学习,再次不做赘述;




      对于页面间的跳转还有很多需要学习和探索的地方,小菜建议多读源码,多学习优秀三方库的实现方式;如有错误,请多多指导!


来源: 阿策小和尚

发布于: 2021 年 06 月 07 日阅读数: 7
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】110 页面间小跳转 (四)