Flutter 提供了一套完整的系統,用於在螢幕之間導覽並處理深層連結 (deep links)。如果您的應用程式較小且不需要複雜的深度連結功能,可以使用 Navigator;而如果您的應用有特定的深度連結與導覽需求,則應同時使用 Router,以正確處理 Android 和 iOS 上的深層連結 (deep links),並在應用於網頁上運行時與網址列 (address bar) 保持同步。

若要設定您的 Android 或 iOS 應用程式以處理深層連結,請參閱 Deep linking

使用 Navigator

#

Navigator 元件 (Widget) 會以堆疊的方式顯示螢幕,並根據目標平台使用正確的轉場動畫。若要導覽至新螢幕,可透過路由的 BuildContext 取得 Navigator,並呼叫命令式方法,例如 push() or pop()

dart
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 的 navigation recipes 或瀏覽 Navigator API 文件

使用命名路由(named routes)

#

具有簡單導覽和深層連結(deep linking)需求的應用程式,可以使用 Navigator 來進行導覽,並透過 MaterialApp.routes 參數處理深層連結:

dart
child: const Text('Open second screen'),
onPressed: () {
  Navigator.pushNamed(context, '/second');
},

/second 代表在 MaterialApp.routes 清單中宣告的 命名路由。完整範例請參考 Flutter Cookbook 的 使用命名路由進行導覽 教學。

限制

#

雖然命名路由可以處理深層連結 (deep links),但其行為始終相同,無法自訂。當平台收到新的深層連結時,Flutter 會在 Navigator 上推入新的 Route,不論使用者目前位於哪個位置。

此外,Flutter 針對使用命名路由的應用程式,並不支援瀏覽器的前進按鈕。因此,我們不建議大多數應用程式使用命名路由。

使用 Router

#

如果 Flutter 應用程式有進階的導覽與路由需求(例如:網頁應用程式需直接連結至每個螢幕,或應用程式中有多個 Navigator 元件 (Widgets)),建議使用如 go_router 這類路由套件,能夠解析路由路徑,並在應用程式收到新的深層連結時,動態設定 Navigator

要使用 Router,請在 MaterialAppCupertinoApp 上切換至 router 建構函式,並提供 Router 設定。像 go_router 這樣的路由套件,通常會提供路由設定,並可如下使用:

dart
child: const Text('Open second screen'),
onPressed: () => context.go('/second'),

由於像 go_router 這類套件是宣告式的,因此當收到深層連結 (deep link) 時,總是會顯示相同的螢幕。

同時使用 Router 與 Navigator

#

RouterNavigator 設計上是可以一起運作的。你可以透過宣告式路由套件(如 go_router)使用 Router API 來導覽,或是直接在 Navigator 上呼叫 push()pop() 這類命令式方法。

當你使用 Router 或宣告式路由套件進行導覽時,Navigator 上的每個路由都是以頁面為基礎(page-backed),也就是它是透過 Page 並搭配 pages 參數於 Navigator 建構函式中建立的。相反地,任何透過呼叫 Navigator.pushshowDialog 所建立的 Route,都會在 Navigator 上新增一個無頁面(pageless)的路由。如果你使用路由套件,則以頁面為基礎的路由永遠可以進行深層連結,而無頁面的路由則無法。

當一個以頁面為基礎RouteNavigator 移除時,之後所有無頁面的路由也會一併被移除。例如,若深層連結導致 Navigator 移除一個以頁面為基礎的路由,則該路由之後(直到下一個以頁面為基礎路由為止)的所有無頁面路由也會被移除。

網頁支援

#

使用 Router 類別的應用程式會與瀏覽器的 History API 整合,讓使用者在點擊瀏覽器的返回與前進按鈕時,獲得一致的體驗。每當你使用 Router 進行導覽時,瀏覽器的歷史堆疊中就會新增一個 History API 項目。按下返回按鈕時,會採用反向時間順序導覽(reverse chronological navigation),也就是將使用者帶回先前透過 Router 顯示的位置。這表示,如果使用者從 Navigator 彈出一個頁面後,再按瀏覽器的返回按鈕,上一個頁面會再次被推回堆疊中。

更多資訊

#

若想進一步了解導覽與路由,請參考以下資源: