Navigation 3 เป็นไลบรารีการนำทางที่ออกแบบมาตั้งแต่ต้นสำหรับ Jetpack Compose บทความนี้จะอธิบายวิธีใช้ Navigation 3 ในแอปพลิเคชัน Wear OS
แนวคิดสำคัญ
NavKey: ตัวระบุที่ปลอดภัยตามประเภทและทำให้เป็นอนุกรมได้สำหรับปลายทาง (หน้าจอ) ในแอปNavBackStack: รายการที่เปลี่ยนแปลงได้ของอินสแตนซ์NavKeyซึ่งแสดงถึงประวัติการนำทาง คุณสามารถเพิ่มและนำรายการออกจากรายการนี้ได้โดยตรงrememberNavBackStack: Composable ที่สร้างและเก็บรักษา Back Stack ไว้เมื่อมีการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดการประมวลผลNavDisplay: คอมโพเนนต์ UI หลักที่สังเกต Back Stack และแสดงหน้าจอที่ใช้งานอยู่EntryProvider: DSL การแมปที่ลิงก์NavKeyกับ UI@ComposableจริงSwipeDismissableSceneStrategy: กลยุทธ์เฉพาะของ Wear ที่ครอบหน้าจอด้วยท่าทางสัมผัสปัดเพื่อปิดและจัดการภาพเคลื่อนไหวกลับในตัว
ขั้นตอนที่ 1: เพิ่มการขึ้นต่อกัน
เพิ่มทรัพยากร Dependency ที่จำเป็นของ Navigation 3, Wear Compose และการเรียงอันดับลงในโปรเจ็กต์
ดึงดูด
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 และ Back Stack
เริ่มต้น Back Stack และกลยุทธ์ฉาก 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: ดำเนินการการนำทาง
เนื่องจาก Back Stack เป็นเพียง MutableList ที่ปรับแต่ง การนำทางจึงตรงไปตรงมาอย่างยิ่ง คุณดำเนินการกับอินสแตนซ์ backStack ได้โดยตรง ดังนี้
- นำทางไปข้างหน้า:
backStack.add(Screen.Details("123")) - นำทางกลับ:
backStack.removeLast()หรือbackStack.removeLastOrNull() - ล้างและรีเซ็ต:
backStack.clear(); backStack.add(Screen.Home)(หรือใช้ การดำเนินการกับรายการเพื่อแทนที่ Stack)
ขั้นตอนที่ 5: (ไม่บังคับ) กำหนดขอบเขต View Model ให้กับปลายทาง
โดยค่าเริ่มต้น ViewModel จะกำหนดขอบเขตไว้ที่ Activity Navigation 3
มีอาร์ติแฟกต์เฉพาะ (lifecycle-viewmodel-navigation3) เพื่อกำหนดขอบเขต ViewModel ให้กับ NavEntry ใน Back Stack อย่างปลอดภัย เมื่อนำปลายทางออกจาก Back Stack ระบบจะล้าง ViewModel
เพิ่มทรัพยากร Dependency:
implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")เพิ่มตัวตกแต่ง Store ของ ViewModel ลงใน
NavDisplay'sentryDecorators. นอกจากนี้ คุณต้องรวมSaveableStateHolderNavEntryDecoratorอย่างชัดเจนเมื่อระบุ ตัวตกแต่งที่กำหนดเองเพื่อเก็บสถานะrememberSaveableของ Compose ไว้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() } } )