首页 > 技术文章 > Flutter 一次退回多个页面

KlllB 2019-11-13 14:59 原文

最近开发的Flutter项目有个需求:app有个页面是绑定卡片,要求绑卡成功后退回查询页面,查询页面与绑卡页面之间有一个页面。

经过简单查询,发现很多技术博客都是介绍的pushReplacementpushAndRemoveUntil这两个方法,但是根据这些博客给出的案例无法实现我的需求,于是我只好去看官方文档。

对于pushReplacement,官方文档的描述如下:Replace the current route of the navigator that most tightly encloses the given context by pushing the given route and then disposing the previous route once the new route has finished animating in.

大概意思是在路由栈中把当前路由的记录换成一个新的路由的记录,具体操作为在新路由入栈后销毁之前的路由。

 

对于pushAndRemoveUntil,官方文档的描述如下:Push the given route onto the navigator that most tightly encloses the given context, and then remove all the previous routes until the predicate returns true.

大概意思是入栈一个新路由,然后把栈中其他路由全部清除,直到判定条件返回true。

 

我目前的需求是从页面1进入页面2,再从页面2进入页面3,然后操作成功返回页面1。路由栈中在返回页面1之前应该是[页面1,页面2,页面3],我需要的效果为在操作成功后路由栈变为[[页面1]。

如果我选择pushReplacement,那么路由栈会变成[页面1,页面2,页面1],跟我的需求不符。我也没有选择pushAndRemoveUntil,一开始我就没选择这个方法,因为我粗略一看认为它无法实现,但是在写这篇文章的时候,我突然想到按照逻辑他应该是可以实现的,于是我进行了测试,按照文档的描述传入2个参数,第一个参数是页面1的路由,第二个参数是判定条件为页面0时返回true。这里有一个问题就是这个判定条件应该怎么写,其实它跟第三个方法一样:它应该是一个返回bool值的函数-->bool Function(Route<dynamic> route)

很多博客都是用的这样的方法:ModalRoute.withName("home"),但是我的这个项目没有使用命名路由,没办法使用这样的语句。于是我试过自己判断 route == MaterialPageRoute(builder:(context){return Home()}),事实证明这样是不行的,因为路由是引用类型,他们两个根本不会相等。最终我在stackoverflow上找到了解决方法:

Navigator.push(
  context,
  MaterialPageRoute(
    settings: RouteSettings(name: "Foo"),
    builder: ...,
  ),
);
 ------------
Navigator.pushAndRemoveUntil(newRoute, ModalRoute.withName("Foo"))

意思是在路由入栈的时候可以给它设置一个名字,这样就算没有使用命名路由系统,可以获取路由的名字。

第三个方法是我原本最终采用的方法:

Navigator.push(
  context,
  MaterialPageRoute(
    settings: RouteSettings(name: "Foo"),
    builder: ...,
  ),
);
----------------
Navigator.popUntil(context, ModalRoute.withName("Foo"))

使用的是popUntil 方法,作用是一直把路由栈中的路由移除出栈,直到判定条件为true。

推荐阅读