穿梭在不同的畫面中 - 固定名稱路由法

紅寶鐵軌客
來關注...
關注/停止關注:紅寶鐵軌客
關注有什麼好處?:當作者有新文章發佈時,「思書」就會自動通知您,讓您更容易與作者互動。
現在就加入《思書》,你就可以關注本作者了!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,讓你寫作不再受限,討論更深入真實,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入
寫程式中、折磨中、享受中 ......
567   0  
·
2021/06/03
·
6分鐘


前文所述,Flutter 有四種 Navigation & Routing 的方式:

N1
直接導航
直接給指定 screen 名稱
N2 固定名稱路由 透過路由跳到指定的 screen 名稱
N3 動態名稱路由 目的地由 widget 中取出,或用 onGenerateRoute()  
N4 動態名稱路由 2.0 使用 State:有 Page 及 Route 兩個新的 API

我們已經學過了「N1/直接導航法」這種直接導航的方式,說直白的,就是把要去的 screen 包成一個 Route,好處是很直接,小缺點是如果常常要去這個 screen,就要寫很多次,所以接下來這種,「N2 / 固定名稱路由法」,說白了,就是一個懶人法,把所有的 screens 列一個表,再給每個 screen 對應一個「路徑名稱」,這樣如果要重複呼叫,就簡單多了。

N2 / 固定名稱路由法

其實這種用「路徑名稱」的方法在各種網站的開發平台上,早就已經用很久了,就叫 routes,路由,Flutter 也沒搞怪,一樣也叫做 routes,用法也很簡單:

  1. 先建立一個 routes,也就是「路徑名稱」對應 screen 的表;
  2. 再將要去的 screen 用 Navigator.pushNamed(路徑名稱) 來呼叫,App 就會跳轉到該頁了。 

講半天,不如直接上碼,如果你剛進來,我們目前的程式碼的開發是停留在這裡:

Flutter 程式寫作風格與管理 Code Organization — 將程式碼依照功能,放入適當的 folder 中,及,取一個好的名稱...
WriterShelf 思書: 紅寶鐵軌客

我們會從這裡開始修改程式,如果你是中途插隊進來了,可以打開來參考裡面的程式碼。

先打開 main.dart,routes 是要寫在 MaterialApp 這個 Widget 裡面:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => MyHomePage(title: 'Happy Recorder v0.0'),
        '/audio': (context) => AudioSession(),
      },
    );
  }
}

我們只改了以下:

  • 第 9~13 行:原來是直接跳到 home: MyHomePage(title: 'Happy Recorder v0.0'), 我們現在改成:
    • 第 9 行:initialRoute 是 App 一開始要去的路徑名稱,一般都設為 '/',也就是無名,我們稱之為 root,網頁根目錄。
    • 第 10~13 行:就是建立這個 App 的 routes,我們就只有兩個,一個是 root,另一個路徑名稱我們取為 audio,對應到 AudioSession screen。

再來就是將原來的 Navigator.push () 改成 Navigator.pushNamed(路徑名稱),我們目前只有一個 screen 有直接連結跳轉,就是 MyHomePage.dart,打開它,把 push() 改成 pushName(/audio):

floatingActionButton: FloatingActionButton(
  //onPressed: _incrementCounter,
  onPressed: () {
    Navigator.pushNamed(context, '/audio');
  },
  ...
),

我們也只改了一行,找到 FloatingActionButton 中的 onPressed,也就是上圖的第 4 行,將原先的落落長的 Navigator.push( content, MaterialPageRoute......... ) 改成很精簡的 Navigator.pushNamed( context,  '/audio' ),就好了,這樣是不是看起來清爽多了。

這樣就改好了。啥!就只改了四行程式碼!沒錯,就是這麼簡單。

好啦,現在我們可以試試看了,請使用 Web 模擬器(因為 App 沒有網址列),執行 run,很好,如我們所預期的,我們看到路徑名稱 audio 出現在網址上了,如下圖:

我們也稱這種網址為「友善網址」:一個讓使用者可以讀懂的網址。

很不幸的,這也不是我們要的導航方式,我們需要一個網址可以直接連到錄音檔的:url.com/audio/class1,但是我們有更接近了。

除此之外,這方法還有其他問題:

  • 直接打路徑名稱 audio 在網址上,會動嗎?很可惜,不會。
  • 同樣的,各位也要測試一下瀏覽器的倒退前進鍵,你應該很快就會發現還是很怪怪的,有的時候可以倒退,有時不行,你現在知道這倒退前進鍵真的很難搞了吧。

 

更多的 navigation 功能

當所有的 screens 都有路徑名稱後,navigator 可以做的事就不止是 push/pop/pushName() 這種「簡單」的堆疊動作而已了,它可以做的更多的「堆疊更改」動作了,例如:

  • pushReplacementNamed:
    • 使用情境像是登入成功後,你不會想讓使用者按倒退鍵時再看到登入 screen;
    • pushReplacementNamed 會將 stack 上的路徑名稱改掉,這個跟下面的 popAndPushNamed 很像,只是這個會使用切換畫面中的「 enter animation 進入動畫」,動畫的部分有點小複雜,我們先跳過,真有興趣可以先看這裡
  • popAndPushNamed:
    • 跟 pushReplacementNamed 幾乎一樣,stack 先 pop 出舊的,再 push 進新的,切換的動作沒差別,只是這個會使用「 exit animation 離開動畫」。
  • pushNamedAndRemoveUntil:
    • 寫法:Navigator.of(context).pushNamedAndRemoveUntil('/screen4', ModalRoute.withName('/screen1')),它會清 Stack 清到 route screen1 然後 push screen4 進去,
    • 使用情境:例如使用者 logout,Navigator Stack 必須要清空然後 push screen4 進去,寫法:Navigator.of(context).pushNamedAndRemoveUntil('/screen4', (Route route) => false);
  • popUntil:
    • 寫法:Navigator.popUntil(context, ModalRoute.withName('/screen2')) ,它會一直 Pop navigator 的 stack 直到 screen2 出現為止。
  • 還有一堆,以上只是比較常用的,想知道更多請看navigator 文件

此外,navigator 還有兩個很有趣的 stack 檢查:

  • maybePop:可以 pop 嗎?如果 stack 中還有東西的話就 pop,不然 pop 到空,程式就結束了。
  • canPop:檢查是不是只剩一個起始的 initial screen 了,return false 就是只剩一個,不能再 pop 了。

 

Navigator.push(content, route)
vs.
Navigator.of(content).push(route)

這兩個有什麼不同?答案是一樣的,不過使用 Navigator.of(content) 時有多兩個選擇性的參數:

  • rootNavigator:寫法是 Navigator.of(context, rootNavigator: true).pushNamed("/route"),這是使用在 nested 巢狀 navigator 中,要不要回到 root 的方法,我這樣寫,大家絕對看不懂,這真的很難用文字來說明,還好,網路總有大神,看看這個連結,上面有很棒的圖解,也有程式碼,看完圖後,再回頭看一次我的說明,你就會豁然開朗了。
  • nullOk:設為 true 時,navigator 可以 pop 到 null,也就是程式關閉。

所以,如果你不需要這兩個功能:Navigator.push(...) = Navigator.of(...).pop(...),兩個寫法是一樣的。

 

這個導航方式也不是我們要的,下一種切換網址的方式會更好嗎?讓我們繼續「試」下去吧!


 


喜歡作者的文章嗎?馬上按「關注」,當作者發佈新文章時,思書™就會 email 通知您。

思書是公開的寫作平台,創新的多筆名寫作方式,能用不同的筆名探索不同的寫作內容,無限寫作創意,如果您喜歡寫作分享,一定要來試試! 《 加入思書》

思書™是自由寫作平台,本文為作者之個人意見。


文章資訊

本文摘自:
分類於:
合計:1516字


分享這篇文章:
關於作者

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




參與討論!
現在就加入《思書》,馬上參與討論!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,用筆名來區隔你討論內容,讓你的討論更深入,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入


看看作者的其他文章


看看思書的其他文章



×
登入
申請帳號

需要幫助
關於思書

暗黑模式?
字體大小
成人內容未過濾
更改語言版本?