Navigation 3 แสดงถึงการเปลี่ยนแปลงพื้นฐานในวิธีที่ Jetpack Compose จัดการสถานะการไปยังส่วนต่างๆ และมีข้อได้เปรียบด้านสถาปัตยกรรมที่สำคัญกว่า Navigation 2
ทำความเข้าใจการเปลี่ยนแปลงด้านสถาปัตยกรรมและขั้นตอนที่จำเป็นในการย้ายข้อมูลแอป Wear Compose จาก Navigation 2 ไปยัง Navigation 3
ข้อได้เปรียบที่สำคัญของ Navigation 3
- การควบคุม Back Stack โดยตรง:
NavBackStackเป็นเพียง รายการNavKeyออบเจ็กต์ที่เปลี่ยนแปลงได้ ซึ่งแสดงถึงประวัติหน้าจอที่ผู้ใช้เข้าชม คุณควบคุมได้เหมือนกับMutableListของ Kotlin ทุกประการ (add,removeLast,clear) โดยจะจัดการรายการโดยตรงเพื่อดำเนินการการไปยังส่วนต่างๆ เช่น การเพิ่มคีย์เพื่อไปข้างหน้าหรือการนำคีย์ออกเพื่อย้อนกลับ - การออกแบบแบบ Compose-First: ระบบจะสร้าง Back Stack เป็นสถานะที่สังเกตได้มาตรฐาน การแก้ไขประวัติการนำทางของคุณจะทำงานเหมือนกับการอัปเดตสถานะ Compose อื่นๆ โดยจะทริกเกอร์การจัดองค์ประกอบใหม่โดยอัตโนมัติเพื่อแสดงหน้าจอปัจจุบัน
- ปลอดภัยตามประเภทโดยค่าเริ่มต้น: ระบบจะนำเส้นทางที่อิงตามสตริงออกทั้งหมด การนำทางจะใช้ออบเจ็กต์ข้อมูลและคลาสข้อมูลที่ซีเรียลไลซ์ได้
- การนำเสนอที่แยกออกจากกัน (กลยุทธ์ฉาก): เลเยอร์การเปลี่ยน UI
(
NavDisplayและSwipeDismissableSceneStrategy) จะแยกออกจากกันโดยสิ้นเชิงจากการติดตามสถานะ (NavBackStack) ซึ่งช่วยให้ผสานรวมการเปลี่ยนการนำทางใน Wear OS ได้ง่ายขึ้น
ขั้นตอนการย้ายข้อมูล
1. อัปเดตทรัพยากร Dependency
นำทรัพยากร Dependency androidx.wear.compose:compose-navigation เก่าออกและเพิ่มทรัพยากร Dependency ใหม่ของ Navigation 3 ที่แยกกัน พร้อมกับการรองรับการซีเรียลไลซ์ของ Kotlin
นำออก:
implementation("androidx.wear.compose:compose-navigation:...")
เพิ่ม:
implementation("androidx.navigation3:navigation3-runtime:...") // State logic
implementation("androidx.navigation3:navigation3-ui:...") // Display logic
implementation("androidx.wear.compose:compose-navigation3:...") // Wear gestures
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:...") // Requires compiler plugin
2. อัปเดตปลายทางเพื่อใช้ NavKey
ใน Navigation 2 คุณอาจใช้สตริงหรือออบเจ็กต์ทั่วไปสำหรับการกำหนดเส้นทาง ใน
Navigation 3 คุณ ต้อง ใช้อินเทอร์เฟซมาร์กเกอร์ NavKey และ
ใส่คำอธิบายประกอบ @Serializable ในออบเจ็กต์หน้าจอทุกรายการ
ทำไมต้องดำเนินการดังกล่าว เพื่อให้มั่นใจว่าระบบจะบันทึกและกู้คืน Back Stack ได้เมื่อการประมวลผลสิ้นสุดลง navigation3-runtime ที่อยู่เบื้องหลังอาศัยkotlinx-serialization ในการซีเรียลไลซ์สถานะ
ก่อน (Navigation 2 - เส้นทางทั่วไปที่ปลอดภัยตามประเภท):
sealed class Nav2Screen { data object Landing : Nav2Screen() data object List : Nav2Screen() }
หลัง (Navigation 3 - NavKey + ซีเรียลไลซ์ได้):
@Serializable sealed interface MigrationScreen : NavKey { @Serializable data object Landing : MigrationScreen @Serializable data object List : MigrationScreen }
3. แทนที่ตรรกะการกำหนดเส้นทาง (NavController เป็น NavBackStack)
แทนที่ NavController ด้วย NavBackStack ที่เริ่มต้นผ่าน
rememberNavBackStack นอกจากนี้ คุณยังต้องสร้างอินสแตนซ์
SwipeDismissableSceneStrategy สำหรับ Wear OS โดยเฉพาะด้วย
ก่อน (Navigation 2):
val navController = rememberSwipeDismissableNavController()
หลัง (Navigation 3):
val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey) val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()
4. แทนที่ NavHost ด้วย NavDisplay และ DSL entryProvider
คอนเทนเนอร์ NavHost และตัวสร้าง composable("route") { ... } ภายใน
DSL จะถูกแทนที่ด้วย NavDisplay และ entryProvider {
entry<Key> { ... } } DSL
ก่อน (Navigation 2):
SwipeDismissableNavHost(navController = navController, startDestination = "menu") { composable("menu") { GreetingScreen( onShowList = { navController.navigate("list") } ) } composable("list") { ListScreen() } }
หลัง (Navigation 3):
NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { entry<MigrationScreen.Landing> { GreetingScreen( onShowList = { backStack.add(MigrationScreen.List) } ) } entry<MigrationScreen.List> { ListScreen() } } )