Flutter中如何实现无Context跳转详解

背景介绍

Navigator.of(context).push(MaterialPageRoute(builder: (context){
   return DemoPage();
  }));

在日常的项目开发中,我们一般push一个新页面是用上面的方法的,利用Navigator.of(context)来进行push或者pop操作。

缺点:这种情况是必须传context的,目的是为了利用Navigator.of(context)来获取到NavigatorState对象,然后才能进行push或者pop操作。

那如果我要实现在项目的任何地方都可以push一个新页面的话,而这个地方有可能获取不到context,所以这个时候,就需要实现无context跳转。

解决方案

无context跳转,本质就是不必要我们每次都去传context参数,然后利用一些操作直接去获取到当前的NavigatorState。

方案1:利用GlobalKey

  • 在Flutter中,利用GolbalKey利用获取到对应Widget的State对象。所以,这里,我们可以通过一个GlobalKey的key值,来获取到NavigatorState对象。
  • MaterialApp中包装了WidgetsApp,而WidgetsApp包装了Navigator,并且将 Navigator的key属性作为navigatorKey暴露出来了。所以,我们可以通过设置navigatorKey,然后利用这个key去获取到NavigatorState对象。

这里贴一下相关的源码,具体的大家可以自己去看源码。

MaterialApp类:

WidgetsApp类:可以看出,我们定义的navigatorKey,最后是会传给Navigator的key值,所以我们在外面就可以通过key.currentState()方法来获取到这里的NavigatorState对象了。

class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserver {

 GlobalKey<NavigatorState> _navigator;

 void _updateNavigator() {
 _navigator = widget.navigatorKey ?? GlobalObjectKey<NavigatorState>(this);
 }

 @override
 Widget build(BuildContext context) {
 Widget navigator;
 if (_navigator != null) {
  navigator = Navigator(
  key: _navigator,
  initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
   ? WidgetsBinding.instance.window.defaultRouteName
   : widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName,
  onGenerateRoute: _onGenerateRoute,
  onUnknownRoute: _onUnknownRoute,
  observers: widget.navigatorObservers,
  );
 }
}

简单的代码实现

1、定义一个GlobalKey< NavigatorState>对象

 static GlobalKey<NavigatorState> navigatorKey=GlobalKey();

2、创建MaterialApp的对象的时候,将navigatorKey赋值给MaterialApp。

MaterialApp(
   navigatorKey: Router.navigatorKey,
)

使用GlobalKey在任意地方获取NavigatorState对象

navigatorKey.currentState.pushNamed("/login");

方案2:利用NavigatorObserver

  • NavigatorObserver,看这名字,就知道是可以用来监听Navigator的变化。比如当push一个新页面的时候,Navigator会监听到NavigatorState发生变化,回调didPush()方法。

注意:NavigatorObserver里面定义了一个NavigatorState对象navigator,所以我们可以通过自定义NavigatorObserver,然后直接利用这个navigator对象来做页面push或者pop操作,这样的话,我们就不用自己去利用context去获取navigatorState对象了。

MaterialApp类,提供了navigatorObservers属性,这样我们就可以自定义NavigatorObserver去监听Navigator的变化。

NavigatorState类,执行instState对象的时候,会将自身赋值到监听的所有observer对象的_navigator里面。

简单的代码实现

1、自定义NavigatorObserver。

class CustomNavigatorObserver extends NavigatorObserver{
 static CustomNavigatorObserver _instance;

 static CustomNavigatorObserver getInstance() {
 if (_instance == null) {
  _instance = CustomNavigatorObserver();
 }
 return _instance;
 }
}

2、创建MaterialApp的对象的时候,将CustomNavigatorObserver赋值给MaterialApp

MaterialApp(
   navigatorObservers: [CustomNavigatorObserver()],
)

3、使用CustomNavigatorObserver在任意地方进行页面操作

CustomNavigatorObserver.getInstance().navigator.pushNamed("/login");

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Flutter学习教程之Route跳转以及数据传递

    前言 我们知道移动应用页面跳转是非常重要的一部分,几乎我们的程序和用户打交道的就是页面,或者叫view,我们Android基本都是Activity和Fragment.而且Flutter当中叫做Route,它就是与用户打交道的页面.本文详细探索一下Flutter当中页面之间是怎么交互的. Route类似Android中Activity,所以Flutter中的页面跳转类似Android中Activity之间跳转,Intent携带传递的数据. 正文 页面跳转 我们现在看看Flutter中是怎么进行页面

  • Flutter路由的跳转、动画和传参详解(最简单)

    路由 做Android/iOS原生开发的时候,要打开一个新的页面,你得知道你的目标页面对象,然后初始化一个Intent或者ViewController,再通过startActivity或者pushViewController来推出一个新的页面,不能跟web一样,直接丢一个链接地址就跳转到新的页面.当然,可以自己去加一个中间层来实现这些功能. Flutter里面是原生支持路由的.Flutter的framework提供了路由跳转的实现.我们可以直接使用这些功能. Flutter路由介绍 Flutte

  • Flutter中如何实现无Context跳转详解

    背景介绍 Navigator.of(context).push(MaterialPageRoute(builder: (context){ return DemoPage(); })); 在日常的项目开发中,我们一般push一个新页面是用上面的方法的,利用Navigator.of(context)来进行push或者pop操作. 缺点:这种情况是必须传context的,目的是为了利用Navigator.of(context)来获取到NavigatorState对象,然后才能进行push或者pop操

  • Go中groutine通信与context控制实例详解

    目录 需求背景: Groutine的并发控制: Context: 看看代码: 总结 需求背景: 项目中需要定期执行任务A来做一些辅助的工作,A的执行需要在超时时间内完成,如果本次执行超时了,那就不对本次的执行结果进行处理(即放弃这次执行).同时A又依赖B,C两个子任务的执行结果.B, C之间相互独立,可以并行的执行.但无论B,C哪一个执行失败或超时都会导致本次任务执行失败. Groutine的并发控制: go中对于groutine的并发控制有三种解决方案: 通过channel控制. 父grout

  • C语言中强制地址跳转详解

    C语言中强制地址跳转详解 #define jump(TargetAddr ) (*((void(*)())(TargetAddr))() 第一个(( void( * )(  )) ,意思为强制类型转换为一个无形参,无返回值的函数指针,(*(TargetAddr))为跳转地址,但是函数指针变量不能为常数所以要加((void( * )(  )) 进行强制类型转换.最后一个()为执行的意思. 整一条指定的目的是为了跳转到一个绝对地址执行函数. 1.在单片机中可以实现软件复位,比如跳转到0地址. 2.如

  • Flutter在项目中使用动画不使用包实现详解

    目录 前言 正文 1 按下按钮柔软的感觉 2 想要一个像 Instagram 一样的喜欢按钮吗? 3 动画页面过渡 4 动画文字 5 更改/闪动文本样式 前言 动画对于 web 和移动应用程序都非常重要.但是在移动应用程序中不应该使用夸张的动画.简单但是很多动画使你的应用程序更好用.以至于当你点击一个按钮时,一种平滑的感觉或者页面过渡都会影响到你. 正文 1 按下按钮柔软的感觉 class _CustomButtonState extends State<CustomButton> with

  • Web应用中设置Context Path案例详解

    URL:http://hostname.com/contextPath/servletPath/pathInfo Jetty 如果没有contextPath,则默认使用root上下文,root上下文的路径为"/". warName.war 在没有XML IoC文件的情况下: 如果WAR文件名是myapp.war,那么上下文路径是:/myapp: 如果WAR文件名是ROOT.war,那么上下文路径是:/: 如果WAR文件名是ROOT-foobar.war,那么上下文路径是/,虚拟host

  • Flutter的键值存储数据库使用示例详解

    目录 Flutter 键值存储数据库 unqlite unqlite_flutter 快速上手 简单键值对存储 JSON 为什么你应该使用unqlite_flutter? Flutter 键值存储数据库 键值存储是开发中十分常见的需求,在Flutter开发中,一般使用 shared_preferences 插件来实现.shared_preferences 本质上就是将键值对保存到一个XML文件中进行持久化. 而shared_preferences 实际上存在一定缺陷,譬如其性能较差,不适合处理大

  • webpack项目中使用vite加速的兼容模式详解

    目录 前言 目的 要处理的问题 动手 共用 index.html 共用配置 兼容环境变量 自动导入 资源引入 svg-sprite-loader 替代方案 其他 效果 前言 随着公司前端工程越来越大,启动是无尽的等待,修改是焦急的等待. vite 到现在生态也起来了,就有了把项目改造成 vite 的想法,但是项目后面可能要依赖 qiankun 改造成微前端项目,现在 qiankun 对 vite 还没有好的解决方法,我就想采取一个折中的办法,保留 webpack,再兼容 vite,两条路都留着.

  • Flutter Widgets之标签类控件Chip详解

    目录 概述: RawChip Chip InputChip ChoiceChip FilterChip 总结: 概述: Flutter 标签类控件大全ChipFlutter内置了多个标签类控件,但本质上它们都是同一个控件,只不过是属性参数不同而已,在学习的过程中可以将其放在放在一起学习,方便记忆. RawChip Material风格标签控件,此控件是其他标签控件的基类,通常情况下,不会直接创建此控件,而是使用如下控件: Chip InputChip ChoiceChip FilterChip

  • flutter Bloc 更新后事件同步与异步详解

    目录 前言 使用方式 Bloc 新形态用法 事件队列的阻塞属性? 前言 最近,小轰参与了公司 flutter 项目关于 Dart 2.0 的空安全升级工作.我们升级了所有依赖的三方库,其中就包括有 Bloc 库.作为一款使用率颇高的状态管理框架, Bloc 在版本迭代中进行了少许结构和细节的优化,下面是小轰对于 Bloc 新版本的使用总结. 使用方式 小轰使用的 Bloc 版本如下 flutter_bloc: ^7.3.1 通过最简单的例子来学习新知识 创建一个包含 加 减 操作的页面,使用 b

  • Flutter封装组动画混合动画AnimatedGroup示例详解

    目录 一.来源 二.AnimatedGroup使用示例: 三.AnimatedGroup源码 最后 一.来源 项目中遇到混合动画的情况,每次实现都需要生命一堆属性,让代码变得杂乱,难以维护. 参考 iOS 组动画 CAAimationGroup, 随花半天时间封装一个混合动画组件 AnimatedGroup. 此组件基于极简.高扩展.高适用的封装原则,基本满足当前项目开发. 二.AnimatedGroup使用示例: // // AnimatedGroupDemo.dart // flutter_

随机推荐