ย้ายข้อมูลไปยัง Navigation 3

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