การนำทาง 3

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

  1. เพิ่มทรัพยากร Dependency:

    implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")
    
  2. เพิ่มตัวตกแต่ง Store ของ ViewModel ลงใน NavDisplay's entryDecorators. นอกจากนี้ คุณต้องรวม 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()
            }
        }
    )