Navigation 3

Navigation 3 是一个从头开始为 Jetpack Compose 设计的导航库。本指南介绍了如何在 Wear OS 应用中实现 Navigation 3。

核心概念

  • NavKey:应用中目的地的类型安全的可序列化标识符。
  • NavBackStack:表示导航历史记录的 NavKey 实例的可变列表。您可以直接从此列表中推送和弹出项。
  • rememberNavBackStack:一种可组合项,用于在配置更改和进程终止后创建并保留返回堆栈。
  • NavDisplay:用于观察返回堆栈并渲染活动屏幕的核心界面组件。
  • EntryProvider:一种映射 DSL,用于将 NavKey 关联到其对应的实际 @Composable 界面。
  • SwipeDismissableSceneStrategy:Wear 专用策略,可将您的屏幕封装在滑动关闭手势中,并处理内置的返回动画。

第 1 步:添加依赖项

向您的项目添加所需的 Navigation 3、Wear Compose 和序列化依赖项。

Groovy

dependencies {
    // Core Navigation 3 APIs
    implementation "androidx.navigation3:navigation3-runtime:1.2.0-alpha02"
    implementation "androidx.navigation3:navigation3-ui:1.2.0-alpha02"

    // Wear OS specific Navigation 3 integration
    implementation "androidx.wear.compose:compose-navigation3:1.6.1"

    // Kotlinx Serialization for type-safe routing
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0"
}

Kotlin

dependencies {
    // Core Navigation 3 APIs
    implementation("androidx.navigation3:navigation3-runtime:1.2.0-alpha02")
    implementation("androidx.navigation3:navigation3-ui:1.2.0-alpha02")

    // Wear OS specific Navigation 3 integration
    implementation("androidx.wear.compose:compose-navigation3:1.6.1")

    // Kotlinx Serialization for type-safe routing
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0")
}

第 2 步:定义目标平台 (NavKey)

界面定义为实现 NavKey 接口的强类型可序列化对象或数据类。

@Serializable
sealed interface Screen : NavKey {
    @Serializable
    data object Home : Screen

    @Serializable
    data class Details(val itemId: String) : Screen
}

第 3 步:设置 NavDisplay 和返回堆栈

在应用根目录中,初始化返回堆栈和 Wear OS 场景策略,然后将它们插入 NavDisplay

// 1. Create the persistent back stack starting at the Home screen
val backStack = rememberNavBackStack(Screen.Home)

// 2. Initialize the Wear OS swipe-to-dismiss strategy
val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()

// 3. Render the NavDisplay
NavDisplay(
    backStack = backStack,
    sceneStrategies = listOf(strategy),
    entryProvider = entryProvider {
        // 4. Map keys to Composables
        entry<Screen.Home> {
            HomeScreen(
                onNavigateToDetails = { id -> backStack.add(Screen.Details(id)) }
            )
        }
        entry<Screen.Details> { key ->
            DetailsScreen(
                itemId = key.itemId,
                onBack = { backStack.removeAt(backStack.lastIndex) }
            )
        }
    }
)

第 4 步:执行导航操作

由于返回堆栈只是一个自定义的 MutableList,因此导航非常简单。您可以直接对 backStack 实例执行操作:

  • 向前导航backStack.add(Screen.Details("123"))
  • 返回backStack.removeLast()backStack.removeLastOrNull()
  • 清除并重置backStack.clear(); backStack.add(Screen.Home)(或使用列表操作替换堆栈)。

第 5 步:(可选)将 ViewModel 的范围限定为目的地

默认情况下,ViewModel 的范围限定为 Activity。Navigation 3 提供了一个专用制品 (lifecycle-viewmodel-navigation3),用于将 ViewModel 安全地限定到返回堆栈上的 NavEntry。当目的地从返回堆栈中弹出时,ViewModel 会被清除。

  1. 添加依赖项:

    implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")
    
  2. 将 ViewModel 存储区装饰器添加到 NavDisplayentryDecorators 中。在提供自定义装饰器以保留 Compose rememberSaveable 状态时,您还必须明确添加 SaveableStateHolderNavEntryDecorator

    NavDisplay(
        backStack = backStack,
        sceneStrategies = listOf(strategy),
        entryDecorators = listOf(
            rememberSaveableStateHolderNavEntryDecorator(),
            rememberViewModelStoreNavEntryDecorator()
        ),
        entryProvider = entryProvider {
            entry<Screen.Home> {
                // Any viewModel() requested here will be scoped to this NavEntry
                val viewModel: HomeViewModel = viewModel()
            }
        }
    )