導覽是指使用者在應用程式中移動的方式。使用者通常透過輕觸或點按 UI 元素進行互動,應用程式則會回應並顯示新內容。如果使用者想返回先前的內容,可以使用返回手勢或輕觸返回按鈕。
建立導航狀態模型
如要模擬這種行為,最方便的方法是使用內容堆疊。當使用者「向前」瀏覽新內容時,系統會將該內容推送至堆疊頂端。當使用者從該內容「返回」時,系統會將該內容從堆疊中移除,並顯示先前的內容。在導覽術語中,這個堆疊通常稱為「返回堆疊」,因為它代表使用者可以返回的內容。
建立返回堆疊
在 Navigation 3 中,返回堆疊實際上不含內容。而是包含內容參照,稱為鍵。索引鍵可以是任何類型,但通常是簡單、可序列化的資料類別。使用參照而非內容有以下好處:
- 只要將鍵推入返回堆疊,即可輕鬆瀏覽。
- 只要金鑰可序列化,返回堆疊就能儲存至永久儲存空間,在設定變更和程序終止後仍可保留。這點很重要,因為使用者預期離開應用程式後,稍後返回時能從上次離開的地方繼續,並顯示相同的內容。詳情請參閱「儲存返回堆疊」。
Navigation 3 API 的一個關鍵概念是「您擁有返回堆疊的控制權」。程式庫:
- 預期返回堆疊會是快照狀態支援的
List<T>,其中T是返回堆疊keys的類型。您可以使用Any,也可以提供自己的強型別金鑰。當您看到「push」或「pop」等字詞時,基礎實作會從清單結尾新增或移除項目。 - 觀察返回堆疊,並使用
NavDisplay在 UI 中反映其狀態。
以下範例說明如何建立鍵和返回堆疊,以及如何修改返回堆疊,以回應使用者導覽事件:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
將金鑰解析為內容
Navigation 3 使用 NavEntry 建立內容模型,這個類別包含可組合函式。代表目的地,也就是使用者可以前往和返回的單一內容。
NavEntry 也可以包含中繼資料,也就是內容相關資訊。容器物件 (例如 NavDisplay) 可以讀取這項中繼資料,協助決定如何顯示 NavEntry 的內容。舉例來說,中繼資料可用於覆寫特定 NavEntry 的預設動畫。NavEntry metadata 是 String 鍵與 Any 值的對應,提供多功能資料儲存空間。
如要將 key 轉換為 NavEntry,請建立項目供應器。這個函式會接受 key,並傳回該 key 的 NavEntry。建立 NavDisplay 時,通常會定義為 lambda 參數。
建立項目供應器的方法有兩種:直接建立 lambda 函式,或使用 entryProvider DSL。
直接建立 Entry Provider 函式
您通常會使用 when 陳述式建立 Entry Provider 函式,並為每個索引鍵建立分支。
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
使用 entryProvider DSL
entryProvider DSL 可避免測試每種金鑰類型,並為每種金鑰類型建構 NavEntry,進而簡化 lambda 函式。請使用 entryProvider 建構函式。如果找不到索引鍵,也會包含預設備用行為 (擲回錯誤)。
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
請注意程式碼片段中的下列事項:
entry可用來定義具有指定類型和可組合內容的NavEntryentry接受metadata參數來設定NavEntry.metadata
顯示返回堆疊
返回堆疊代表應用程式的導覽狀態。每當返回堆疊變更時,應用程式 UI 都應反映新的返回堆疊狀態。在 Navigation 3 中,NavDisplay 會觀察返回堆疊,並據此更新 UI。請使用下列參數建構:
- 返回堆疊:類型應為
SnapshotStateList<T>,其中T是返回堆疊索引鍵的類型。它是可觀察的List,因此在變更時會觸發NavDisplay的重組。 entryProvider,用於將返回堆疊中的索引鍵轉換為NavEntry物件。- 您可以視需要為
onBack參數提供 lambda。當使用者觸發返回事件時,系統會呼叫這個函式。
以下範例說明如何建立 NavDisplay。
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
根據預設,NavDisplay 會在單一窗格版面配置中,顯示返回堆疊最上方的 NavEntry。以下錄製內容顯示這個應用程式的執行情形:

NavDisplay 預設行為,包含兩個目的地。目的地生命週期
NavDisplay 會根據場景層級和項目層級限制,使用自訂 LifecycleOwner 限制 NavEntry 的生命週期狀態。
如要進一步瞭解 Compose 中的生命週期,請參閱「Jetpack Compose 中的生命週期」。
場景層級生命週期限制
NavDisplay 會管理有效 Scene 的生命週期。場景層級上限的決定方式如下:
非疊加場景:
如果是重疊場景,例如對話方塊或底部功能表:
RESUMED:僅適用於最上層、目前有效的疊加場景。STARTED:如果基礎疊加層場景被較新的疊加層覆蓋,則上限為STARTED。
初階生命週期狀態
程式庫會根據每個 NavEntry 在返回堆疊中的存在狀態,管理其最大生命週期狀態:
RESUMED:如果項目存在於目前的返回堆疊中,其生命週期最多可達RESUMED(受限於場景層級上限)。CREATED:如果項目不再位於返回堆疊中,例如已彈出但仍顯示在畫面上,且正在播放動畫,則程式庫會將其生命週期嚴格限制在CREATED。這項限制可確保背景或結束項目在完成結束轉換時,停止執行有效工作,例如收集流程或啟動繫結至RESUMED或STARTED狀態的協同程式。
如何結合
舉例來說,NavEntry 的最終生命週期狀態會解析如下:
| 情境 | 場景層級上限 | 入門級上限 | 有效上限 |
|---|---|---|---|
| 有效項目,固定畫面 (無轉場或疊加層) | RESUMED |
RESUMED |
RESUMED |
| 轉換期間 (前往或離開) 的有效項目 | STARTED |
RESUMED |
STARTED |
| 有效項目,由疊加層覆蓋 (例如開啟對話方塊) | STARTED |
RESUMED |
STARTED |
| 彈出式項目,動畫淡出 | STARTED 或 RESUMED |
CREATED |
CREATED |
正在統整內容
下圖說明 Navigation 3 中各種物件之間的資料流程:
導覽事件會啟動變更。系統會根據使用者互動,在返回堆疊中新增或移除金鑰。
返回堆疊狀態變更會觸發內容擷取。
NavDisplay(用於轉譯返回堆疊的可組合函式) 會觀察返回堆疊。在預設設定中,它會以單一窗格版面配置顯示最頂層的返回堆疊項目。當返回堆疊上的頂端索引鍵變更時,NavDisplay會使用這個索引鍵向項目供應器要求對應的內容。項目供應商提供內容。項目提供者是將索引鍵解析為
NavEntry的函式。收到NavDisplay的金鑰後,項目供應器會提供相關聯的NavEntry,其中包含金鑰和內容。顯示內容。
NavDisplay接收NavEntry並顯示內容。