Flutter路由基础使用

路由管理

路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewController。

所谓路由管理,就是管理页面之间如何跳转,通常也可被称为导航管理。

Flutter中的路由管理和原生开发类似,无论是Android还是iOS,导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作,而路由管理主要是指如何来管理路由栈。

Flutter路由的详细使用

(一)Navigator

在Android中,我们开启新的页面是Activity。在iOS中,我们开启新的页面是ViewControllers。在Flutter中,每一个页面都是小部件, 我们如何开启到新的页面呢?

Flutter给我们提供了一个API,叫做Navigator

Navigator 继承自 StatefulWidget,它也是小组件,它有很多相关静态函数,可以帮我们达到页面跳转和数据交互的功能:

函数 作用
push 将设置的router信息推送到Navigator上,实现页面跳转。
of 主要是获取 Navigator最近实例的好状态。
pop 导航到新页面,或者返回到上个页面。
canPop 判断是否可以导航到新页面
maybePop 可能会导航到新页面
popAndPushNamed 指定一个路由路径,并导航到新页面。
popUntil 反复执行pop 直到该函数的参数predicate返回true为止。
pushAndRemoveUntil 将给定路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
pushNamed 将命名路由推送到Navigator。
pushNamedAndRemoveUntil 将命名路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
pushReplacement 路由替换。
pushReplacementNamed 这个也是替换路由操作。推送一个命名路由到Navigator,新路由完成动画之后处理上一个路由。
removeRoute 从Navigator中删除路由,同时执行Route.dispose操作。
removeRouteBelow 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
replace 将Navigator中的路由替换成一个新路由。
replaceRouteBelow 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由。

(二)路由的操作方式

(1)使用Navigator.push实现发送路由,Navigator.pop返回上一个页面。

  @optionalTypeArgs
  static Future<T> push<T extends Object>(BuildContext context, Route<T> route) {
    return Navigator.of(context).push(route);
  }

push函数的参数1是 上下文,参数2是 Router,我们这里使用的是 Router的孙子类(好几层继承的子类)MaterialPageRouter 这个类。

该类必须要传入一个闭包函数 WidgetBuilder,该闭包函数的参数是 BuildContext对象,我们这里使用的是匿名函数的形式,加上胖箭头符号,简写成这样:builder: (context) => new App(); 相信大家看到这里也基本能看明白这句表达式的含义。

返回上一个页面使用

 Navigator.pop(context);

页面A 的代码如下图所示:
第一点:push使用

1.pushNamed

Navigator.of(context).pushNamed('routeName');

此种方法只是简单的将我们需要进入的页面push到栈顶,以此来显示当前页面,其参数是一个字符串类型,传入的是页面对应的路由名称
该路由名称需要在程序主入口中进行定义。定义方法为:

void main() {
  runApp(
      new MaterialApp(
        home: new Screen1(),
        routes: <String, WidgetBuilder> {
          '/screen1': (BuildContext context) => new Screen1(),
          '/screen2' : (BuildContext context) => new Screen2(),
          '/screen3' : (BuildContext context) => new Screen3(),
        },
      )
  );
}

使用:Navigator.of(context).pushNamed('/screen1'); 直接进入screen1页面(每次都将新建一个新的页面)

2.1 pushReplacementNamed

Navigator.of(context).pushReplacementNamed('/screen4');

指把当前页面在栈中的位置替换成跳转的页面(替换导航器的当前路由,通过推送路由[routeName]),当新的页面进入后,之前的页面将执行dispose方法。
下面为官方说明:

Replace the current route of the navigator that most tightly encloses the
given context by pushing the route named [routeName] and then disposing
the previous route once the new route has finished animating in.

 @optionalTypeArgs
  Future<T> pushReplacementNamed<T extends Object, TO extends Object>(
    String routeName, {
    TO result,
    Object arguments,
  }) {
    return pushReplacement<T, TO>(_routeNamed<T>(routeName, arguments: arguments), result: result);
  }

即比如当前从页面1进入页面2,在页面2使用
Navigator.of(context).pushReplacementNamed('/screen3');进入页面3,当进入了页面3后,页面2将执行dispose方法,此时在页面3返回时,会回到页面1.

使用情况:例如
从SplashScreen到HomeScreen。它应该只显示一次,用户不应该再从主屏幕回到它。在这种情况下,由于我们将要进入一个全新的屏幕,
我们可能想要使用这个方法来实现它的enter animation属性。

2.2 pushReplacement

Navigator.pushReplacement( context, MaterialPageRoute(builder: (BuildContext context) => screen4()));

这个用法跟2.1相同,只是路由的传递有差别,上方的是传递路由名称(页面对应的名称,需在入口定义(本文第一点)),而后者只需new对应页面即可,而且可以传递
参数(传参方式类似于本文后续所说的传递方法)。
默认使用MaterialPageRoute

3.popAndPushNamed

Navigator.popAndPushNamed(context, '/screen4');

指将当前页面pop,然后跳转到制定页面(将当前路由弹出导航器,并将命名路由推到它的位置。)
下面为官方说明:

Pop the current route off the navigator that most tightly encloses the
given context and push a named route in its place.

使用情况:例如
在购物应用中,有产品列表,用户在产品列表中可以通过筛选,来进一步选择商品,在这个过程中,用户点击筛选按钮时,会进入筛选条件选择界面,当用户点击
确定筛选按钮时,应弹出筛选界面,并使用新的筛选条件进入产品列表。这种情况popAndPushNamed就更合适了。

4.pushNamedAndRemoveUntil

Navigator.of(context).pushNamedAndRemoveUntil('/screen4', (Route<dynamic> route) => false);

指将制定的页面加入到路由中,然后将其他所有的页面全部pop, (Route<dynamic> route) => false将确保删除推送路线之前的所有路线。
这时候将打开一个新的screen4页面

Push the route with the given name onto the navigator, and then remove all
the previous routes until the `predicate` returns true.

使用情况:例如
当用户点击了退出登录时,我们需要进入某一个页面(比如点退出登录后进入了登录页),这个时候用户点击返回时不应该能进入任何一个页面,这种情况就可以使用。

5.1 pushNamedAndRemoveUntil

Navigator.of(context).pushNamedAndRemoveUntil('/screen4', ModalRoute.withName('/screen1'));

指将制定的页面加入到路由中,然后将之前的路径移除知道制定的页面为止(将具有给定名称的路由推到导航器上,然后删除所有路径前面的路由直到'predicate'返回true为止。)
这时候将销毁栈内除了screen4的页面,点击直接去栈内screen4,这时screen4会重新build

Push the route with the given name onto the navigator, and then remove all
the previous routes until the `predicate` returns true.

使用情况:例如
一个购物应用程序的例子!或者任何需要支付交易的应用程序。因此,在这些应用程序中,一旦用户完成了支付事件,所有与交易或购物车相关的屏幕都应该从堆栈中删除,用户应该进入到支付确认页面。单击back按钮应将它们返回到产品列表或主屏幕。
使用实例:
1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/screen1'));
这时候如果在页面4点击返回,将会直接退出程序。
1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/'));
这时候如果在页面4点击返回,将会直接回到页面1。
1-->2-->1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/screen1'));
这时候如果在页面4点击返回,将会回到第二个1页面。

5.2 pushAndRemoveUntil

  Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute(builder: (BuildContext context) => new  screen4()),
  ModalRoute.withName('/'),

这种方法跟上述方法作用相同,不同之处在于,上述传递的是路由名称,这个名称需要你在入口处进行路由指定,而这种则无需指定,直接new 出来即可,
而且可以传递参数。(看其名称即可发现差别pushNamedAndRemoveUntil与pushAndRemoveUntil)使用这种作用如下
1-->2-->3,3到4时使用此方法,这时候如果在页面4点击返回,将会直接回到页面1。

如果使用

Navigator.pushAndRemoveUntil(
    context,
    MaterialPageRoute(builder: (BuildContext context) => Screen4()),
      (Route<dynamic> route) => false,
);

这时候进入4后。4将成为唯一的一个页面。其他页面都将pop出栈,这个跟上述pushNamedAndRemoveUntil也一致。

6.popUntil

Navigator.popUntil(context, ModalRoute.withName('/screen2'));

有些应用场景下,用户可能不得不填写一个由三部分组成的长表单,该表单可能在移动应用程序的三个连续屏幕中显示。现在在表单的第三个页面,用户决定取消填写表单。用户单击Cancel,就会弹出所有之前的与表单相关的屏幕,并将用户带回主屏幕,从而丢失所有与表单相关的数据(在这种情况下,这是我们想要的)。我们不会在这里推出任何新东西,只是回到以前的路线。

pop

1.Navigator.of(context).maybePop();

maybePop 会自动进行判断,如果当前页面pop后,会显示其他页面,不会出现问题,则将执行当前页面的pop操作
否则将不执行。

2.Navigator.of(context).canPop();

canPop 判断当前页面能否进行pop操作,并返回bool值

3.Navigator.of(context).pop();

直接退出当前页面

传参和参数返回

传参的方式很简单,在需要接收参数的页面进行参数定义,并加入其构造函数中,在跳转到该页面时,使用MaterialPageRoute并在页面中传入参数即可。

String params;
 Navigator.push(context, new MaterialPageRoute(builder: (BuildContext context) => new mainPage(params)));
接收参数
class mainPage extends StatelessWidget {
  final String userName;
  mainPage(this.userName);
  @override
  Widget build(BuildContext context) {
    print(userName);
}

带返回值的页面跳转:

String userName = "yinll";
Navigator.push(
    context,
    new MaterialPageRoute(
        builder: (BuildContext context) =>
        new Screen5(userName))).then((data){
          result =data;
          print(result);
});

然后screen5中,在返回时使用:Navigator.of(context).pop('这是页面5返回的参数');
在pop中写上返回的的值,这时候在上方的then中即可得到返回的数据。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容