Flutter开发 -- 导航
省流:官网也在强推go_router,各位看官可以跳到使用路由那块直接看。
导航对于任何应用程序都非常重要。它为各种平台提供的导航 API 提供了统一的抽象。Flutter 为导航提供了两种类型的 API:命令式和声明式。## 命令式导航最常用的一种导航的方式,也是最简单的一种。命令式导航由一个栈的Widget组成,通过push压栈,通过pop从栈里弹出。push方法让你导航的一个新的页面,而pop则从当前页面返回到上一个页面。我们来看一个简单的例子:
注意push之后就会跳转到DetailScreen了。
在DetailScreen调用pop可以返回:
Navigator
Navigator类提供了导航需要的所有功能。同时,还提供了一个pushReplaceent的方法。这个方法和push类似,但是会把当前路由删除,也就是说导航到新的页面之后再导航回来是不可能的。这个场景正好适合登录,登录成功之后用户无法回退到登录页面。
命名导航
使用命名导航,你可以只用字符串就切换不同的页面。这主要是通过定义一个路由字典实现的。
定义路由
路由的定义由字符串为Key,页面实例为值的字典组成。然后传入到MaterialApp的routes属性:
在我们的todo app里面的修改可以是这样的:
随后就要修改HomeScreen跳转的方法:注释掉的就是我们之前用的导航代码。现在使用了Navigator.pushNamed这个方法,然后传入定义好的路由的名称detail就可以跳转到详细页面了。
传递数据
在导航中传递参数
就如上例中我们提到的,从todo 列表页跳转到详细页的时候还显示的是一个可以回退的按钮。这是我们为了显示导航的功能而做的。但是这是不够的。在跳转到详细页的时候本来应该展示的是todo的详情内容。这就需要导航到新的页面的时候还要把数据也一起传递过去。另外还要介绍一个情况就是,从新的路由里返回数据。
最简单的一种方法是在push的时候,初始化DetailScreen的时候给他传入一个参数,也就是给DetailScreen添加一个构造函数参数。这里就不细说了。
真正的参数是这样传递的:
在push的时候,在MaterialPageRoute里给settings值。然后,在DetailScreen中把参数读取出来:final todo = ModalRoute.of(context)!.settings.arguments as TodoItem;就是用来读取导航传递的参数的。
在导航中返回数据
现在来实现返回数据的功能。比如,如果一个用户查看了todo的内容,那么就返回以后弹出一个“已读”的snackbar。就像这样:
首先修改HomeScreen的代码:
主要看第二行,给push的方法加一个await,然后读取一个返回值给result赋值。得到值之后显示一个snackbar说明todo详情已读。
之后修改DetailScreen页面。需要改的地方不多,只要改pop加一个需要返回的值作为参数。像这样:Navigator.pop(context, '${todo.content} is read');。
以上都是在命令导航中传递参数的方法。先在看看如何在命名导航中传递参数。
首先,需要在MaterialApp中配置routes属性。这个前文已经讲过了。然后在pushNamed加上要传递的参数。
然后在DetailScreen里读取参数。还是老方法:
在新一版本的Flutter中,引入了基于Page的导航。这些在第三方库中广泛使用,比如go_router。有兴趣的可以了解一下。
注意:Flutter不推荐使用命名导航的方式。主要是因为命名路由在支持deep link和flutter web的时候有问题。
使用路由
这是一个声明式的方式定义路由的方法。在前面讲到的内容中,如果要同时push或者pop多个页面,或者对当前页面以外的路由操作都不是很容易。Router,我们要讲的,可以非常容易的处理以上的问题。
具体基于pages的路由可以参考官网。在后续的deep link的讲解中会用到go_router。所以,我们这里着重讲解一下这个库的一些常用方法。
首先下载go_router包。
然后去掉之前的所有路由的代码,添加基于go_router的代码:
修改的时候,只需要把之前的MaterialApp改成MaterialApp.router。其他的不用改,之后把routes改成routerConfig。
routerConfig添加一些路由:
“/”这个路由对应的就是HomeScreen,“/detail”对应的就是DetailScreen页面。“/settings”对应的就是SettingsScreen。
在settings这个路由下还有一个子路由:“isolate”。这是go_router的子路由。
在导航到下一个页面的时候可以使用context.push(目标路由)的方式也可以使用context.go(目标路由)的方式。二者路由有区别。使用go的方式,之前的路由历史会被清理出路由栈。在使用的时候需要注意!
使用push跳转到设置页:
使用go跳转到isolate页面:
就是这么简单!
使用go_router的情况下,如何传递参数呢?也很简单。
路径参数(path params)
查询参数(query params)
在导航的时候可以这样:
附加参数(extra params)
导航的时候:
带值pop
运行起来看看吧!
转载自:https://juejin.cn/post/7358688805157371941