Navigation 2:NavController 与 Graph · AndroidX 源码指南
AAndroidX 源码指南
Navigation
应用导航 · androidx.navigation

Navigation 2:NavController 与 Graph2.10.0-beta01

使用类型安全 route、NavHost、NavOptions 和 NavBackStackEntry 建立 Compose 导航。

最后更新 2026-08-01

类型化 route

@Serializable object Home
@Serializable data class Profile(val userId: String)

val navController = rememberNavController()

NavHost(navController, startDestination = Home) {
    composable<Home> {
        HomeScreen(onProfile = { id ->
            navController.navigate(Profile(id))
        })
    }
    composable<Profile> { entry ->
        val route = entry.toRoute<Profile>()
        ProfileScreen(route.userId)
    }
}

route 参数原则:只携带定位目标所需的小型参数(ID、枚举)。完整对象由目标页通过 repository 读取——避免参数变旧、过大或难以恢复。

navController.navigate(
    route = Profile(userId),
    navOptions = NavOptions.Builder()
        .setLaunchSingleTop(true)      // 顶部已有该路由则复用
        .setPopUpTo(Home, inclusive = false)  // 弹出到 Home(保留 Home)
        .setRestoreState(true)         // 恢复目标状态
        .build(),
)
选项作用
launchSingleTop目标已在栈顶则不重复入栈
popUpTo(route)弹出到指定路由(inclusive 决定是否连它也弹)
popUpToSaveState / restoreState保存/恢复被弹出的状态
enterAnim/exitAnim转场动画
composable<Profile> { entry ->
    val userId = entry.toRoute<Profile>().userId
    // SavedStateHandle:进程重建恢复
    val handle = entry.savedStateHandle
    ProfileScreen(userId)
}
  • entry.toRoute&lt;T&gt;() 解析类型化参数。
  • entry.savedStateHandle 拿该 entry 的 SavedStateHandle(配合 ViewModel)。
  • currentBackStackEntryFlow 观察 entry 变化——UI 优先用 Compose 专用扩展。

返回与结果

// 目标页返回结果
navController.previousBackStackEntry
    ?.savedStateHandle
    ?.set("result", value)
navController.popBackStack()

// 源页接收
composable<Home> { entry ->
    val result = entry.savedStateHandle.getStateFlow("result", null)
    ...
}

常见陷阱

  • 重复导航:事件重放 → 同一目标多次 push。导航是一次性 UI 行为,在事件消费边界处理;launchSingleTop 不是重复事件补丁。
  • 大对象当参数:不可序列化或 Bundle 超限 → 崩溃;只传 ID。
  • 深度链接/恢复状态:需要 restoreState 才能恢复到被弹出的页面状态。
  • Graph 层级混乱:用嵌套 graph(navigation&lt;T&gt;)组织结构,避免扁平大图。
  • 忘记依赖androidx.navigation:navigation-compose + navigation-common(KMP)。

复制即用

import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
import kotlinx.serialization.Serializable

@Serializable object Home
@Serializable data class Profile(val userId: String)

@Composable
fun AppNav() {
    val navController = rememberNavController()

    NavHost(navController, startDestination = Home) {
        composable<Home> {
            HomeScreen(onProfile = { id ->
                navController.navigate(Profile(id)) {
                    launchSingleTop = true
                }
            })
        }
        composable<Profile> { entry ->
            val userId = entry.toRoute<Profile>().userId
            ProfileScreen(userId, onBack = { navController.popBackStack() })
        }
    }
}

要点

  • 类型化 route + NavHost + composable<T>;参数只带小型定位数据。
  • NavOptions 控制 singleTop/popUpTo/状态恢复/动画。
  • SavedStateHandle 在 entry 上,配合 ViewModel 做恢复。
  • 一次性导航事件在消费边界处理,别用 singleTop 掩盖重复。

相关页面