第 28 课2026.08.13
普通详情页需要返回上一页,而登录、支付完成等一次性流程结束后,不应该再返回旧页面。正确整理返回栈可以避免“登录成功后按返回键又看到登录页”。
第 28 课:Compose 导航返回栈
知识点
使用 popBackStack() 和 popUpTo() 管理 Compose Multiplatform 的页面返回栈。
用途
普通详情页需要返回上一页,而登录、支付完成等一次性流程结束后,不应该再返回旧页面。正确整理返回栈可以避免“登录成功后按返回键又看到登录页”。
核心概念
navigate()默认把新目的地压到栈顶。popBackStack()移除当前目的地,回到前一个页面。popUpTo<Route>()在跳转时弹出栈中指定路由上方的页面。inclusive = true表示连指定路由本身也一起移除。launchSingleTop = true避免栈顶重复出现同一个目的地。
示例代码
登录成功后跳到首页,并把登录页从返回栈中移除:
kotlin
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import kotlinx.serialization.Serializable
@Serializable
data object Login
@Serializable
data object Home
@Serializable
data object Detail
@Composable
fun App() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Login,
) {
composable<Login> {
Button(
onClick = {
navController.navigate(Home) {
popUpTo<Login> {
inclusive = true
}
launchSingleTop = true
}
},
) {
Text("登录")
}
}
composable<Home> {
Button(onClick = { navController.navigate(Detail) }) {
Text("打开详情")
}
}
composable<Detail> {
Button(onClick = { navController.popBackStack() }) {
Text("返回首页")
}
}
}
}执行登录跳转后,栈从 [Login] 变为 [Home];进入详情页后变为 [Home, Detail],点击返回则恢复为 [Home]。
5 分钟练习
新增 Checkout 和 Receipt 两个路由。支付完成后从 Checkout 跳到 Receipt,同时移除 Checkout,避免用户返回支付页。
参考答案
kotlin
@Serializable
data object Checkout
@Serializable
data object Receipt
composable<Checkout> {
Button(
onClick = {
navController.navigate(Receipt) {
popUpTo<Checkout> {
inclusive = true
}
}
},
) {
Text("完成支付")
}
}
composable<Receipt> {
Text("支付成功")
}与上一课的联系
上一课学习了用类型安全路由传递页面参数;今天继续管理这些路由在返回栈中的生命周期,决定哪些页面应保留、哪些一次性页面应在完成后移除。