บันทึกและจัดการสถานะการนําทาง

ส่วนต่อไปนี้จะอธิบายกลยุทธ์ในการบันทึก Back Stack และ จัดเก็บสถานะที่เชื่อมโยงกับรายการใน Back Stack

บันทึก Back Stack ของคุณ

การตรวจสอบว่าสถานะการนำทางของแอปยังคงอยู่ตลอดเหตุการณ์ในวงจรต่างๆ รวมถึงการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดการประมวลผลเป็นสิ่งสำคัญต่อประสบการณ์ของผู้ใช้ที่ดี ใน Navigation 3 คุณเป็นเจ้าของ Back Stack จึงไม่มี หลักเกณฑ์ที่เข้มงวดเกี่ยวกับวิธีสร้างหรือบันทึก อย่างไรก็ตาม Navigation 3 มี วิธีการที่สะดวกซึ่งช่วยให้คุณบันทึก Back Stack ได้ ดังนี้ rememberNavBackStack

ใช้ rememberNavBackStack

ฟังก์ชันที่ประกอบกันได้ที่ชื่อ rememberNavBackStack ออกแบบมาเพื่อสร้าง Back Stack ที่ยังคงอยู่เมื่อมีการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดการประมวลผล

หากต้องการให้ rememberNavBackStack ทำงานได้อย่างถูกต้อง คีย์แต่ละรายการใน Back Stack ของคุณ ต้องเป็นไปตามข้อกำหนดต่อไปนี้

  • ใช้NavKeyอินเทอร์เฟซ: คีย์ทุกรายการใน Back Stack ต้องใช้ อินเทอร์เฟซ NavKey ซึ่งทำหน้าที่เป็นอินเทอร์เฟซเครื่องหมายที่ส่งสัญญาณไปยัง ไลบรารีว่าบันทึกคีย์ได้
  • มี@Serializableคำอธิบายประกอบ: นอกเหนือจากการใช้ NavKey แล้ว คุณต้องทำเครื่องหมายคลาสและออบเจ็กต์หลักด้วยคำอธิบายประกอบ @Serializable

ข้อมูลโค้ดต่อไปนี้แสดงการติดตั้งใช้งาน rememberNavBackStack อย่างถูกต้อง

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

จดจำ Back Stack ด้วยประเภทข้อมูลย่อยของ NavKey

ฟังก์ชันที่ประกอบกันได้ rememberNavBackStack จะแสดงผล NavBackStack<NavKey> หากแอปกำหนดประเภทย่อยของ NavKey ซึ่งคีย์ทั้งหมด สืบทอดมาจากประเภทย่อยนี้ คุณจะรักษาการพิมพ์นั้นไว้ได้โดยการใช้ฟังก์ชัน remember ที่กำหนดเอง ดังนี้

@Serializable
sealed interface MyAppNavKey : NavKey

@Serializable
data object ScreenA: MyAppNavKey

@Serializable
data class ScreenB(val id: String): MyAppNavKey

@Composable
fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> {
    return rememberSerializable(serializer = serializer()) {
        NavBackStack(*elements)
    }
}

@Composable
fun MyApp() {
    // defaultNavBackStack is NavBackStack<NavKey>
    val defaultNavBackStack = rememberNavBackStack(ScreenA)
    // myAppNavBackStack is NavBackStack<MyAppNavKey>
    val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA)
}

ดูตัวอย่างเพิ่มเติม รวมถึงวิธีจัดการ Polymorphism แบบเปิดได้ที่ NavBackStackSamples

อีกทางเลือก: จัดเก็บใน ViewModel

อีกวิธีหนึ่งในการจัดการ Back Stack คือการจัดเก็บไว้ใน ViewModel หากต้องการให้ข้อมูลคงอยู่เมื่อการประมวลผลสิ้นสุดลงเมื่อใช้ ViewModel หรือพื้นที่เก็บข้อมูลที่กำหนดเองอื่นๆ คุณต้องทำดังนี้

  • ตรวจสอบว่าคีย์ของคุณสามารถแปลงเป็นอนุกรมได้: เช่นเดียวกับ rememberNavBackStack คีย์การนำทางต้องแปลงเป็นอนุกรมได้
  • จัดการการซีเรียลไลซ์และการดีซีเรียลไลซ์ด้วยตนเอง: คุณมีหน้าที่ บันทึกการแสดงผลที่ซีเรียลไลซ์ของแต่ละคีย์ด้วยตนเอง และ ดีซีเรียลไลซ์จากพื้นที่เก็บข้อมูลถาวร (เช่น SharedPreferences ฐานข้อมูล หรือไฟล์) เมื่อแอปเข้าสู่เบื้องหลังหรือได้รับการกู้คืน

การกำหนดขอบเขต ViewModel วินาทีถึง NavEntry วินาที

ViewModels ใช้เพื่อคงสถานะที่เกี่ยวข้องกับ UI ไว้เมื่อมีการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหน้าจอ โดยค่าเริ่มต้น ViewModels จะกำหนดขอบเขตไว้ที่ ViewModelStoreOwnerที่ใกล้ที่สุด ซึ่งโดยปกติคือ Activity หรือ Fragment

อย่างไรก็ตาม คุณอาจต้องการกำหนดขอบเขต ViewModel ให้กับ NavEntry ที่เฉพาะเจาะจง (เช่น หน้าจอหรือปลายทางที่เฉพาะเจาะจง) ใน Back Stack แทนที่จะเป็น Activity ทั้งหมด ซึ่งจะช่วยให้มั่นใจว่าระบบจะคงสถานะของ ViewModel ไว้เฉพาะในขณะที่ NavEntry นั้นเป็นส่วนหนึ่งของ Back Stack และจะล้างเมื่อมีการป๊อป NavEntry

ไลบรารีส่วนเสริม androidx.lifecycle:lifecycle-viewmodel-navigation3 มีNavEntryDecorator ที่ช่วยให้ทำสิ่งนี้ได้ ตัวตกแต่งนี้จะระบุ ViewModelStoreOwnerสำหรับแต่ละ NavEntry เมื่อคุณสร้าง ViewModel ภายในเนื้อหาของ NavEntry (เช่น ใช้ viewModel() ใน Compose) ระบบจะกำหนดขอบเขตโดยอัตโนมัติ ไปยังคีย์ของ NavEntry นั้นใน Back Stack ซึ่งหมายความว่าระบบจะสร้าง ViewModel เมื่อเพิ่ม NavEntry ลงใน Back Stack และจะล้างเมื่อนำออก

หากต้องการใช้ NavEntryDecorator เพื่อกำหนดขอบเขตของ ViewModel กับ NavEntry ให้ทำตามขั้นตอนต่อไปนี้

  1. เพิ่มทรัพยากร Dependency androidx.lifecycle:lifecycle-viewmodel-navigation3 ลงในไฟล์ app/build.gradle.kts
  2. เพิ่ม rememberSaveableStateHolderNavEntryDecorator() เริ่มต้นลงในรายการ entryDecorators เมื่อสร้าง NavDisplay
  3. เพิ่ม rememberViewModelStoreNavEntryDecorator() ลงในรายการ entryDecorators

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSaveableStateHolderNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)