Navigation 3

Navigation 3 是專為 Jetpack Compose 從頭設計的導覽程式庫。本指南說明如何在 Wear OS 應用程式中實作 Navigation 3。

核心概念

  • NavKey:應用程式中目的地的可序列化型別安全 ID。
  • NavBackStack:代表導覽記錄的 NavKey 例項可變動清單。您可以直接從這個清單推送及彈出項目。
  • rememberNavBackStack:可組合函式,用於建立及保存返回堆疊,確保設定變更和程序終止後仍可使用。
  • NavDisplay:核心 UI 元件,可觀察返回堆疊並轉譯有效畫面。
  • EntryProvider:對應 DSL,可將 NavKey 連結至實際的 @Composable UI。
  • 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。提供自訂裝飾器時,您也必須明確加入 SaveableStateHolderNavEntryDecorator,才能保留 Compose rememberSaveable 狀態:

    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()
            }
        }
    )