Flutter路由基礎(chǔ)使用

路由管理

路由(Route)在移動(dòng)開發(fā)中通常指頁(yè)面(Page)幸逆,這跟web開發(fā)中單頁(yè)應(yīng)用的Route概念意義是相同的,Route在Android中通常指一個(gè)Activity,在iOS中指一個(gè)ViewController漫雕。

所謂路由管理,就是管理頁(yè)面之間如何跳轉(zhuǎn)峰鄙,通常也可被稱為導(dǎo)航管理浸间。

Flutter中的路由管理和原生開發(fā)類似,無(wú)論是Android還是iOS吟榴,導(dǎo)航管理都會(huì)維護(hù)一個(gè)路由棧魁蒜,路由入棧(push)操作對(duì)應(yīng)打開一個(gè)新頁(yè)面,路由出棧(pop)操作對(duì)應(yīng)頁(yè)面關(guān)閉操作,而路由管理主要是指如何來(lái)管理路由棧兜看。

Flutter路由的詳細(xì)使用

(一)Navigator

在Android中锥咸,我們開啟新的頁(yè)面是Activity。在iOS中细移,我們開啟新的頁(yè)面是ViewControllers搏予。在Flutter中,每一個(gè)頁(yè)面都是小部件弧轧, 我們?nèi)绾伍_啟到新的頁(yè)面呢雪侥?

Flutter給我們提供了一個(gè)API,叫做Navigator

Navigator 繼承自 StatefulWidget,它也是小組件精绎,它有很多相關(guān)靜態(tài)函數(shù)速缨,可以幫我們達(dá)到頁(yè)面跳轉(zhuǎn)和數(shù)據(jù)交互的功能:

函數(shù) 作用
push 將設(shè)置的router信息推送到Navigator上,實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)代乃。
of 主要是獲取 Navigator最近實(shí)例的好狀態(tài)鸟廓。
pop 導(dǎo)航到新頁(yè)面,或者返回到上個(gè)頁(yè)面襟己。
canPop 判斷是否可以導(dǎo)航到新頁(yè)面
maybePop 可能會(huì)導(dǎo)航到新頁(yè)面
popAndPushNamed 指定一個(gè)路由路徑引谜,并導(dǎo)航到新頁(yè)面。
popUntil 反復(fù)執(zhí)行pop 直到該函數(shù)的參數(shù)predicate返回true為止擎浴。
pushAndRemoveUntil 將給定路由推送到Navigator员咽,刪除先前的路由,直到該函數(shù)的參數(shù)predicate返回true為止贮预。
pushNamed 將命名路由推送到Navigator贝室。
pushNamedAndRemoveUntil 將命名路由推送到Navigator,刪除先前的路由仿吞,直到該函數(shù)的參數(shù)predicate返回true為止滑频。
pushReplacement 路由替換。
pushReplacementNamed 這個(gè)也是替換路由操作唤冈。推送一個(gè)命名路由到Navigator峡迷,新路由完成動(dòng)畫之后處理上一個(gè)路由。
removeRoute 從Navigator中刪除路由你虹,同時(shí)執(zhí)行Route.dispose操作绘搞。
removeRouteBelow 從Navigator中刪除路由,同時(shí)執(zhí)行Route.dispose操作傅物,要替換的路由是傳入?yún)?shù)anchorRouter里面的路由夯辖。
replace 將Navigator中的路由替換成一個(gè)新路由。
replaceRouteBelow 將Navigator中的路由替換成一個(gè)新路由董饰,要替換的路由是是傳入?yún)?shù)anchorRouter里面的路由蒿褂。

(二)路由的操作方式

(1)使用Navigator.push實(shí)現(xiàn)發(fā)送路由圆米,Navigator.pop返回上一個(gè)頁(yè)面。

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

push函數(shù)的參數(shù)1是 上下文啄栓,參數(shù)2是 Router榨咐,我們這里使用的是 Router的孫子類(好幾層繼承的子類)MaterialPageRouter 這個(gè)類。

該類必須要傳入一個(gè)閉包函數(shù) WidgetBuilder谴供,該閉包函數(shù)的參數(shù)是 BuildContext對(duì)象块茁,我們這里使用的是匿名函數(shù)的形式,加上胖箭頭符號(hào)桂肌,簡(jiǎn)寫成這樣:builder: (context) => new App(); 相信大家看到這里也基本能看明白這句表達(dá)式的含義数焊。

返回上一個(gè)頁(yè)面使用

 Navigator.pop(context);

頁(yè)面A 的代碼如下圖所示:
第一點(diǎn):push使用

1.pushNamed

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

此種方法只是簡(jiǎn)單的將我們需要進(jìn)入的頁(yè)面push到棧頂,以此來(lái)顯示當(dāng)前頁(yè)面,其參數(shù)是一個(gè)字符串類型崎场,傳入的是頁(yè)面對(duì)應(yīng)的路由名稱
該路由名稱需要在程序主入口中進(jìn)行定義佩耳。定義方法為:

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'); 直接進(jìn)入screen1頁(yè)面(每次都將新建一個(gè)新的頁(yè)面)

2.1 pushReplacementNamed

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

指把當(dāng)前頁(yè)面在棧中的位置替換成跳轉(zhuǎn)的頁(yè)面(替換導(dǎo)航器的當(dāng)前路由,通過(guò)推送路由[routeName])谭跨,當(dāng)新的頁(yè)面進(jìn)入后干厚,之前的頁(yè)面將執(zhí)行dispose方法。
下面為官方說(shuō)明:

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);
  }

即比如當(dāng)前從頁(yè)面1進(jìn)入頁(yè)面2螃宙,在頁(yè)面2使用
Navigator.of(context).pushReplacementNamed('/screen3');進(jìn)入頁(yè)面3蛮瞄,當(dāng)進(jìn)入了頁(yè)面3后,頁(yè)面2將執(zhí)行dispose方法谆扎,此時(shí)在頁(yè)面3返回時(shí)挂捅,會(huì)回到頁(yè)面1.

使用情況:例如
從SplashScreen到HomeScreen。它應(yīng)該只顯示一次堂湖,用戶不應(yīng)該再?gòu)闹髌聊换氐剿邢取T谶@種情況下,由于我們將要進(jìn)入一個(gè)全新的屏幕无蜂,
我們可能想要使用這個(gè)方法來(lái)實(shí)現(xiàn)它的enter animation屬性伺糠。

2.2 pushReplacement

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

這個(gè)用法跟2.1相同,只是路由的傳遞有差別斥季,上方的是傳遞路由名稱(頁(yè)面對(duì)應(yīng)的名稱训桶,需在入口定義(本文第一點(diǎn))),而后者只需new對(duì)應(yīng)頁(yè)面即可泻肯,而且可以傳遞
參數(shù)(傳參方式類似于本文后續(xù)所說(shuō)的傳遞方法)渊迁。
默認(rèn)使用MaterialPageRoute

3.popAndPushNamed

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

指將當(dāng)前頁(yè)面pop,然后跳轉(zhuǎn)到制定頁(yè)面(將當(dāng)前路由彈出導(dǎo)航器灶挟,并將命名路由推到它的位置。)
下面為官方說(shuō)明:

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

使用情況:例如
在購(gòu)物應(yīng)用中毒租,有產(chǎn)品列表稚铣,用戶在產(chǎn)品列表中可以通過(guò)篩選箱叁,來(lái)進(jìn)一步選擇商品,在這個(gè)過(guò)程中惕医,用戶點(diǎn)擊篩選按鈕時(shí)耕漱,會(huì)進(jìn)入篩選條件選擇界面,當(dāng)用戶點(diǎn)擊
確定篩選按鈕時(shí)抬伺,應(yīng)彈出篩選界面螟够,并使用新的篩選條件進(jìn)入產(chǎn)品列表。這種情況popAndPushNamed就更合適了峡钓。

4.pushNamedAndRemoveUntil

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

指將制定的頁(yè)面加入到路由中妓笙,然后將其他所有的頁(yè)面全部pop, (Route<dynamic> route) => false將確保刪除推送路線之前的所有路線。
這時(shí)候?qū)⒋蜷_一個(gè)新的screen4頁(yè)面

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

使用情況:例如
當(dāng)用戶點(diǎn)擊了退出登錄時(shí)能岩,我們需要進(jìn)入某一個(gè)頁(yè)面(比如點(diǎn)退出登錄后進(jìn)入了登錄頁(yè))寞宫,這個(gè)時(shí)候用戶點(diǎn)擊返回時(shí)不應(yīng)該能進(jìn)入任何一個(gè)頁(yè)面,這種情況就可以使用拉鹃。

5.1 pushNamedAndRemoveUntil

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

指將制定的頁(yè)面加入到路由中辈赋,然后將之前的路徑移除知道制定的頁(yè)面為止(將具有給定名稱的路由推到導(dǎo)航器上,然后刪除所有路徑前面的路由直到'predicate'返回true為止膏燕。)
這時(shí)候?qū)N毀棧內(nèi)除了screen4的頁(yè)面钥屈,點(diǎn)擊直接去棧內(nèi)screen4,這時(shí)screen4會(huì)重新build

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

使用情況:例如
一個(gè)購(gòu)物應(yīng)用程序的例子!或者任何需要支付交易的應(yīng)用程序坝辫。因此焕蹄,在這些應(yīng)用程序中,一旦用戶完成了支付事件阀溶,所有與交易或購(gòu)物車相關(guān)的屏幕都應(yīng)該從堆棧中刪除腻脏,用戶應(yīng)該進(jìn)入到支付確認(rèn)頁(yè)面。單擊back按鈕應(yīng)將它們返回到產(chǎn)品列表或主屏幕银锻。
使用實(shí)例:
1-->2-->3,3到4時(shí)使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/screen1'));
這時(shí)候如果在頁(yè)面4點(diǎn)擊返回永品,將會(huì)直接退出程序。
1-->2-->3,3到4時(shí)使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/'));
這時(shí)候如果在頁(yè)面4點(diǎn)擊返回击纬,將會(huì)直接回到頁(yè)面1鼎姐。
1-->2-->1-->2-->3,3到4時(shí)使用Navigator.pushNamedAndRemoveUntil(context,"/screen4",ModalRoute.withName('/screen1'));
這時(shí)候如果在頁(yè)面4點(diǎn)擊返回,將會(huì)回到第二個(gè)1頁(yè)面更振。

5.2 pushAndRemoveUntil

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

這種方法跟上述方法作用相同炕桨,不同之處在于,上述傳遞的是路由名稱肯腕,這個(gè)名稱需要你在入口處進(jìn)行路由指定献宫,而這種則無(wú)需指定,直接new 出來(lái)即可实撒,
而且可以傳遞參數(shù)姊途。(看其名稱即可發(fā)現(xiàn)差別pushNamedAndRemoveUntil與pushAndRemoveUntil)使用這種作用如下
1-->2-->3,3到4時(shí)使用此方法涉瘾,這時(shí)候如果在頁(yè)面4點(diǎn)擊返回,將會(huì)直接回到頁(yè)面1捷兰。

如果使用

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

這時(shí)候進(jìn)入4后立叛。4將成為唯一的一個(gè)頁(yè)面。其他頁(yè)面都將pop出棧贡茅,這個(gè)跟上述pushNamedAndRemoveUntil也一致秘蛇。

6.popUntil

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

有些應(yīng)用場(chǎng)景下,用戶可能不得不填寫一個(gè)由三部分組成的長(zhǎng)表單顶考,該表單可能在移動(dòng)應(yīng)用程序的三個(gè)連續(xù)屏幕中顯示×藁梗現(xiàn)在在表單的第三個(gè)頁(yè)面,用戶決定取消填寫表單村怪。用戶單擊Cancel秽浇,就會(huì)彈出所有之前的與表單相關(guān)的屏幕,并將用戶帶回主屏幕甚负,從而丟失所有與表單相關(guān)的數(shù)據(jù)(在這種情況下柬焕,這是我們想要的)。我們不會(huì)在這里推出任何新東西梭域,只是回到以前的路線斑举。

pop

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

maybePop 會(huì)自動(dòng)進(jìn)行判斷,如果當(dāng)前頁(yè)面pop后病涨,會(huì)顯示其他頁(yè)面富玷,不會(huì)出現(xiàn)問(wèn)題,則將執(zhí)行當(dāng)前頁(yè)面的pop操作
否則將不執(zhí)行既穆。

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

canPop 判斷當(dāng)前頁(yè)面能否進(jìn)行pop操作缅疟,并返回bool值

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

直接退出當(dāng)前頁(yè)面

傳參和參數(shù)返回

傳參的方式很簡(jiǎn)單拌倍,在需要接收參數(shù)的頁(yè)面進(jìn)行參數(shù)定義,并加入其構(gòu)造函數(shù)中,在跳轉(zhuǎn)到該頁(yè)面時(shí)荚虚,使用MaterialPageRoute并在頁(yè)面中傳入?yún)?shù)即可添怔。

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

帶返回值的頁(yè)面跳轉(zhuǎn):

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

然后screen5中续徽,在返回時(shí)使用:Navigator.of(context).pop('這是頁(yè)面5返回的參數(shù)');
在pop中寫上返回的的值畏妖,這時(shí)候在上方的then中即可得到返回的數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踢代,一起剝皮案震驚了整個(gè)濱河市盲憎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胳挎,老刑警劉巖饼疙,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異串远,居然都是意外死亡宏多,警方通過(guò)查閱死者的電腦和手機(jī)儿惫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門澡罚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伸但,“玉大人,你說(shuō)我怎么就攤上這事留搔「郑” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵隔显,是天一觀的道長(zhǎng)却妨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)括眠,這世上最難降的妖魔是什么彪标? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮掷豺,結(jié)果婚禮上捞烟,老公的妹妹穿的比我還像新娘。我一直安慰自己当船,他們只是感情好题画,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著德频,像睡著了一般苍息。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上壹置,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天竞思,我揣著相機(jī)與錄音,去河邊找鬼钞护。 笑死盖喷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的患亿。 我是一名探鬼主播传蹈,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼步藕!你這毒婦竟也來(lái)了惦界?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咙冗,失蹤者是張志新(化名)和其女友劉穎沾歪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雾消,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灾搏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年挫望,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狂窑。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡媳板,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泉哈,到底是詐尸還是另有隱情蛉幸,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布丛晦,位于F島的核電站奕纫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烫沙。R本人自食惡果不足惜匹层,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锌蓄。 院中可真熱鬧升筏,春花似錦、人聲如沸煤率。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蝶糯。三九已至洋只,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昼捍,已是汗流浹背识虚。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妒茬,地道東北人担锤。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乍钻,于是被迫代替她去往敵國(guó)和親肛循。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為博主原創(chuàng)文章银择,轉(zhuǎn)載請(qǐng)注明出處多糠! 時(shí)隔許久,繼之前發(fā)的Flutter入門(環(huán)境配置)文章之后浩考,終于有...
    Yinll閱讀 13,204評(píng)論 8 17
  • Flutter的設(shè)計(jì)貌似對(duì)前端同學(xué)比較友好夹孔,言歸正傳,先從原理開始,然后是具體的case,好搭伤,我們開始: 小提示:...
    白袍君閱讀 1,381評(píng)論 0 2
  • 在原生開發(fā)中怜俐,安卓和IOS自有控制頁(yè)面(Activity身堡、ViewControl)跳轉(zhuǎn)的功能,在flutter中佑菩,...
    前端拾遺閱讀 1,166評(píng)論 0 0
  • Navigator 參數(shù) push 將設(shè)置的router信息推送到Navigator上盾沫,實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)裁赠。 of 主要...
    沐沐小火柴閱讀 868評(píng)論 0 1
  • 路由初體驗(yàn) 路由(Routes)是什么佩捞?路由是屏幕或應(yīng)用程序頁(yè)面的抽象绞幌。 Flutter 使我們能夠優(yōu)雅地管理路由...
    Meandni閱讀 4,214評(píng)論 0 16