ส่วนต่อไปนี้จะอธิบายกลยุทธ์ในการบันทึกสแต็กย้อนกลับและจัดเก็บสถานะที่เชื่อมโยงกับรายการในสแต็กย้อนกลับ
บันทึกสแต็กย้อนกลับ
การตรวจสอบว่าสถานะการนำทางของแอปยังคงอยู่ตลอดเหตุการณ์ต่างๆ ในวงจรชีวิต รวมถึงการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดกระบวนการ เป็นสิ่งสำคัญเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี ใน Navigation 3 คุณเป็นผู้ควบคุมสแต็กย้อนกลับเอง ดังนั้นจึงไม่มีหลักเกณฑ์ที่เข้มงวดเกี่ยวกับวิธีสร้างหรือบันทึกสแต็กย้อนกลับ อย่างไรก็ตาม Navigation 3 มีเมธอดที่สะดวกสบายซึ่งให้สแต็กย้อนกลับที่บันทึกได้แก่
rememberNavBackStack
ใช้ rememberNavBackStack
ฟังก์ชันที่ประกอบกันได้ rememberNavBackStack ออกแบบมาเพื่อสร้างสแต็กย้อนกลับที่ยังคงอยู่ตลอดการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดกระบวนการ
แต่ละคีย์ในสแต็กย้อนกลับต้องเป็นไปตามข้อกำหนดเฉพาะเพื่อให้ rememberNavBackStack ทำงานได้อย่างถูกต้อง ดังนี้
- ใช้อินเทอร์เฟซ
NavKey: ทุกคีย์ในสแต็กย้อนกลับต้องใช้ อินเทอร์เฟซNavKeyซึ่งทำหน้าที่เป็นอินเทอร์เฟซมาร์กเกอร์ที่ส่งสัญญาณไปยังไลบรารีว่าคีย์สามารถบันทึกได้ - มีคำอธิบายประกอบ
@Serializable: นอกจากจะใช้NavKeyแล้ว คลาสและออบเจ็กต์คีย์ของคุณต้องมีคำอธิบายประกอบ@Serializable
ข้อมูลโค้ดต่อไปนี้แสดงการใช้งาน rememberNavBackStack อย่างถูกต้อง
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
จดจำสแต็กย้อนกลับที่มีประเภทย่อยของ NavKey
ฟังก์ชันที่ประกอบกันได้ rememberNavBackStack จะแสดงผล NavBackStack<NavKey>
หากแอปกำหนดประเภทย่อยของ NavKey เองซึ่งคีย์ทั้งหมดสืบทอดมาจากประเภทย่อยนั้น คุณสามารถรักษาการพิมพ์นั้นไว้ได้โดยการใช้ฟังก์ชันจดจำที่กำหนดเอง ดังนี้
@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) }
ดูตัวอย่างเพิ่มเติม รวมถึงวิธีจัดการกับโพลีมอร์ฟิซึมแบบเปิดได้ที่
NavBackStackSamples
ทางเลือกอื่น: การจัดเก็บใน ViewModel
อีกวิธีหนึ่งในการจัดการสแต็กย้อนกลับคือการจัดเก็บไว้ใน ViewModel
หากต้องการให้ข้อมูลยังคงอยู่เมื่อกระบวนการสิ้นสุดลงขณะใช้ ViewModel หรือพื้นที่เก็บข้อมูลที่กำหนดเองอื่นๆ คุณต้องทำดังนี้
- ตรวจสอบว่าคีย์เป็นแบบอนุกรมได้: คีย์การนำทางต้องเป็นแบบอนุกรมได้เช่นเดียวกับ
rememberNavBackStack - จัดการการทำให้เป็นอนุกรมและการยกเลิกการทำให้เป็นอนุกรมด้วยตนเอง: คุณมีหน้าที่รับผิดชอบในการ
บันทึกการแสดงแบบอนุกรมของแต่ละคีย์ลงในพื้นที่เก็บข้อมูลถาวร (เช่น
SharedPreferences, ฐานข้อมูล หรือไฟล์) และ ยกเลิกการทำให้เป็นอนุกรมจากพื้นที่เก็บข้อมูลดังกล่าวด้วยตนเองเมื่อแอปเข้าสู่เบื้องหลังหรือได้รับการ กู้คืน
การกำหนดขอบเขตอินสแตนซ์ ViewModel ให้กับออบเจ็กต์ NavEntry
ViewModels ใช้เพื่อเก็บสถานะที่เกี่ยวข้องกับ UI ไว้ตลอดการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหน้าจอ โดยค่าเริ่มต้น ViewModels จะกำหนดขอบเขตไว้ที่ ViewModelStoreOwner ที่ใกล้ที่สุด ซึ่งโดยปกติจะเป็น Activity หรือ Fragment
อย่างไรก็ตาม คุณอาจต้องการกำหนดขอบเขต ViewModel ให้กับ NavEntry ที่เฉพาะเจาะจง (เช่น หน้าจอหรือปลายทางที่เฉพาะเจาะจง) ในสแต็กย้อนกลับแทนที่จะเป็น Activity ทั้งหมด ซึ่งจะช่วยให้มั่นใจได้ว่าสถานะของ ViewModel จะยังคงอยู่เฉพาะในขณะที่ NavEntry นั้นเป็นส่วนหนึ่งของสแต็กย้อนกลับ และจะถูกล้างเมื่อมีการนำ NavEntry ออก
ไลบรารีเสริม androidx.lifecycle:lifecycle-viewmodel-navigation3 มี
NavEntryDecorator ที่ช่วยให้ทำเช่นนี้ได้ ตัวตกแต่งนี้มี ViewModelStoreOwner สำหรับแต่ละ NavEntry เมื่อคุณสร้าง ViewModel ภายในเนื้อหาของ NavEntry (เช่น ใช้ viewModel() ใน Compose) ระบบจะกำหนดขอบเขตให้กับคีย์ของ NavEntry ที่เฉพาะเจาะจงนั้นในสแต็กย้อนกลับโดยอัตโนมัติ ซึ่งหมายความว่าระบบจะสร้าง ViewModel เมื่อมีการเพิ่ม NavEntry ลงในสแต็กย้อนกลับ และจะล้างเมื่อมีการนำออก
หากต้องการใช้ 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 { }, )