導航與路由
Flutter 導航與路由功能概覽
Flutter 提供了一套完整的系統,用於在不同螢幕間導航並處理深層連結(Deep Links)。對於沒有複雜深層連結需求的小型應用,可以使用 Navigator;而對於有特定深層連結和導航需求的應用,則應同時使用 Router,以便在 Android 和 iOS 上正確處理深層連結,並在 Web 應用執行時與位址列保持同步。
如需配置 Android 或 iOS 應用以處理深層連結,請參閱 深層連結。
使用 Navigator
#Navigator 元件使用堆疊(Stack)來顯示螢幕,併為目標平臺使用適當的過渡動畫。要導航到新螢幕,可透過路由的 BuildContext 訪問 Navigator,並呼叫 push() 或 pop() 等命令式方法。
child: const Text('Open second screen'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => const SecondScreen(),
),
);
},
由於 Navigator 維護了一個 Route 物件堆疊(代表歷史堆疊),push() 方法還需要接收一個 Route 物件。MaterialPageRoute 物件是 Route 的子類,它指定了 Material Design 的過渡動畫。有關如何使用 Navigator 的更多示例,請遵循 Flutter Cookbook 中的 導航方案 或訪問 Navigator API 文件。
使用命名路由
#對於導航和深層連結需求簡單的應用,可以使用 Navigator 進行導航,並使用 MaterialApp.routes 引數來處理深層連結。
child: const Text('Open second screen'),
onPressed: () {
Navigator.pushNamed(context, '/second');
},
/second 表示在 MaterialApp.routes 列表中宣告的命名路由。如需完整示例,請遵循 Flutter Cookbook 中的 使用命名路由導航 方案。
侷限性
#儘管命名路由可以處理深層連結,但其行為是固定的,無法自定義。當平臺收到新的深層連結時,無論使用者當前身處何處,Flutter 都會向 Navigator 推入一個新 Route。
此外,Flutter 也不支援對使用命名路由的應用使用瀏覽器的“前進”按鈕。出於這些原因,我們不建議在大多數應用中使用命名路由。建議改用像 go_router 這樣的路由包,或結合使用 Navigator 和 MaterialPageRoute。
使用 Router
#對於具有高階導航和路由需求(例如使用直接連結到每個螢幕的 Web 應用,或包含多個 Navigator 元件的應用)的 Flutter 應用,應使用諸如 go_router 之類的路由包。當應用接收到新的深層連結時,它可以解析路由路徑並配置 Navigator。
要使用 Router,請切換至 MaterialApp 或 CupertinoApp 的 router 建構函式,併為其提供 Router 配置。諸如 go_router 之類的路由包通常會提供路由配置,路由的使用方式如下:
child: const Text('Open second screen'),
onPressed: () => context.go('/second'),
由於像 go_router 這樣的包是宣告式的,因此當接收到深層連結時,它們總是會顯示相同的螢幕。
同時使用 Router 和 Navigator
#Router 和 Navigator 是為了協同工作而設計的。您可以透過宣告式路由包(如 go_router)使用 Router API 進行導航,也可以透過在 Navigator 上呼叫 push() 和 pop() 等命令式方法進行導航。
當您使用 Router 或宣告式路由包進行導航時,Navigator 上的每個路由都是頁面支援的(page-backed),這意味著它是使用 Navigator 建構函式上的 pages 引數從 Page 建立的。相反,透過呼叫 Navigator.push 或 showDialog 建立的任何 Route 都會向 Navigator 新增一個無頁面(pageless)路由。如果您正在使用路由包,頁面支援的路由總是可以被深層連結,而無頁面路由則不能。
當一個頁面支援的 Route 從 Navigator 中移除時,其後所有的無頁面路由也會被移除。例如,如果深層連結透過從 Navigator 移除一個頁面支援的路由來進行導航,那麼其後(直到下一個頁面支援的路由為止)所有的無頁面路由也會被移除。
Web 支援
#使用 Router 類的應用會與瀏覽器的 History API 整合,從而在使用瀏覽器的“後退”和“前進”按鈕時提供一致的體驗。每當您使用 Router 進行導航時,瀏覽器歷史堆疊中都會新增一個 History API 條目。按下後退按鈕會使用逆向時間順序導航,這意味著使用者會被帶回到之前使用 Router 顯示的位置。這意味著,如果使用者從 Navigator 中彈出一個頁面,然後按下瀏覽器後退按鈕,則之前的頁面會被重新推入堆疊。
更多資訊
#有關導航和路由的更多資訊,請查閱以下資源:
- Flutter Cookbook 包含了多個導航方案,展示瞭如何使用
Navigator。 Navigator和RouterAPI 文件中包含了關於如何在不使用路由包的情況下設定宣告式導航的詳細資訊。- 理解導航(Material Design 文件中的頁面)概述了設計應用導航的概念,包括對前進、向上和時間順序導航的解釋。
-
學習 Flutter 的新導航與路由系統(Medium 文章)介紹瞭如何在不使用路由包的情況下直接使用
Router元件。 - Router 設計文件包含了
RouterAPI 的設計動機和實現方案。