NavController
會保留「返回堆疊」包含使用者目的地
。當使用者在整個應用程式中瀏覽畫面時,NavController
會在返回堆疊中新增及移除目的地。
做為堆疊,返回堆疊是「後進,先出」資料結構
因此 NavController
會將項目推送至頂端,並從頂端彈出項目
基本行為
針對返回堆疊的行為,您應考量以下關鍵事項:
- 第一個目的地:使用者開啟應用程式時,
NavController
會將第一個目的地推送至返回堆疊頂端。 - 推送至堆疊:每次呼叫
NavController.navigate()
,都會將指定的目的地推送至堆疊頂端。 - 彈出頂端目的地:輕觸「向上」或「返回」,即可分別呼叫
NavController.navigateUp()
和NavController.popBackStack()
方法。這些方法會將頂端目的地從堆疊中彈出。請參閱「導覽原則」頁面,進一步瞭解「向上」和「返回」的差異。
彈回
NavController.popBackStack()
方法會嘗試將目前的目的地從返回堆疊中彈出,並前往上一個目的地。這樣就能有效將使用者導向導覽記錄中的上一個位置。這個方法會傳回布林值,表示是否已成功彈回至目的地。
彈回至特定目的地
您也可以使用 popBackStack()
前往特定目的地,方法是使用其中一個超載。您可以透過多個超載傳入 ID,例如整數 id
或字串 route
。這些超載會將使用者導向與指定 ID 相關聯的目的地。重要的是,這些超載會彈出該目的地上方的所有堆疊項目。
這些超載也包含 inclusive
布林值,可決定 NavController
是否應在前往指定目的地後,從返回堆疊中彈出該目的地。
請參考以下簡短的程式碼片段範例:
navController.popBackStack(R.id.destinationId, true)
這裡的 NavController
會彈回至目的地,整數 ID 為 destinationId
。由於 inclusive
引數的值為 true
,NavController
也會從返回堆疊中彈出指定目的地。
處理失敗的彈回
popBackStack()
傳回 false
時,對 NavController.getCurrentDestination()
的後續呼叫會傳回 null
。這表示應用程式已從返回堆疊中彈出最後一個目的地。在這種情況下,
一片空白畫面
這可能發生於下列情況:
popBackStack()
未從堆疊中彈出任何項目。popBackStack()
已從返回堆疊中彈出目的地,堆疊現為空白。
如要解決這個問題,您必須前往新目的地,或在活動上呼叫 finish()
以結束活動。請參考下列程式碼片段:
Kotlin
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish()
}
Java
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish();
}
彈出至目的地
從一個目的地導覽至另一個目的地時,如要從返回堆疊中移除目的地,請在相關聯的 navigate()
函式呼叫中加入 popUpTo()
引數。popUpTo()
會指示 Navigation 程式庫在呼叫 navigate()
時,移除返回堆疊中的某些目的地。參數值是返回堆疊中目的地的 ID。ID 可以是整數 id
或字串 route
。
您可以在 inclusive
參數中加入值為 true
的引數,指出您在 popUpTo()
中指定的目的地也應從返回堆疊中彈出。
如要以程式輔助方式實作,請在 NavOptions
中將 popUpTo()
傳遞至 navigate()
,並將 inclusive
設為 true
。此方法適用於 Compose 和 View。
在彈出時儲存狀態
使用 popUpTo
前往目的地時,您可以選擇儲存
返回堆疊和從返回堆疊中彈出的所有目的地狀態。你可以
導覽至該目的地時,還原返回堆疊和目的地
合作執行。這可讓您保留特定目的地的狀態,
多個返回堆疊。
如要以程式輔助方式執行這項操作,請在新增 popUpTo
時指定 saveState = true
您的導覽選項。
您也可以在導覽選項中指定 restoreState = true
,
會自動還原返回堆疊和
目的地。
例如:
navController.navigate(
route = route,
navOptions = navOptions {
popUpTo<A>{ saveState = true }
restoreState = true
}
)
如要在 XML 中啟用儲存及還原狀態功能,請將 popUpToSaveState
定義為 true
在相關聯的 action
中分別以 restoreState
取代 true
。
XML 範例
以下是在 XML 中使用動作的 popUpTo
範例:
<action
android:id="@+id/action_a_to_b"
app:destination="@id/b"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"
app:restoreState=”true”
app:popUpToSaveState="true"/>
Compose 範例
以下是 Compose 中相同動作的完整範例:
@Composable
fun MyAppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
startDestination: Any = A
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable<A> {
DestinationA(
onNavigateToB = {
// Pop everything up to, and including, the A destination off
// the back stack, saving the back stack and the state of its
// destinations.
// Then restore any previous back stack state associated with
// the B destination.
// Finally navigate to the B destination.
navController.navigate(route = B) {
popUpTo<A> {
inclusive = true
saveState = true
}
restoreState = true
}
},
)
}
composable<B> { DestinationB(/* ... */) }
}
}
@Composable
fun DestinationA(onNavigateToB: () -> Unit) {
Button(onClick = onNavigateToB) {
Text("Go to A")
}
}
如要採取更精細的做法,可以透過下列方式變更呼叫 NavController.navigate()
的方法:
// Pop everything up to the destination_a destination off the back stack before
// navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a")
}
// Pop everything up to and including the "destination_a" destination off
// the back stack before navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a") { inclusive = true }
}
// Navigate to the "search” destination only if we’re not already on
// the "search" destination, avoiding multiple copies on the top of the
// back stack
navController.navigate("search") {
launchSingleTop = true
}
如需將選項傳遞至 NavController.navigate()
的一般資訊,請參閱「使用選項導覽」指南。
使用動作彈出
使用動作進行導覽時,您可以視需要從返回堆疊中彈出其他目的地。舉例來說,如果應用程式有起始登入流程,則在使用者登入後,您應將所有與登入相關的目的地從返回堆疊中彈出,讓「返回」按鈕不會將使用者導回登入流程。
延伸閱讀
如需詳細資訊,請參閱以下頁面: