ส่วนต่อไปนี้จะอธิบายกลยุทธ์ในการบันทึก 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 ให้ทำตามขั้นตอนต่อไปนี้
- เพิ่มทรัพยากร Dependency
androidx.lifecycle:lifecycle-viewmodel-navigation3ลงในไฟล์app/build.gradle.kts - เพิ่ม
rememberSaveableStateHolderNavEntryDecorator()เริ่มต้นลงในรายการentryDecoratorsเมื่อสร้างNavDisplay - เพิ่ม
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 { }, )