ใช้ตรรกะหรือ Wrapper กับปลายทาง

คุณสามารถระบุข้อมูลเพิ่มเติมหรือใช้ตรรกะเดียวกันกับ ปลายทางได้โดยใช้คลาส NavEntryDecorator คลาสนี้จะห่อหุ้มแต่ละ NavEntryในสแต็กย้อนกลับด้วยฟังก์ชันที่ใช้ร่วมกันได้ กล่าวอีกนัยหนึ่งคือ ตกแต่งเนื้อหาของรายการ

สร้างตัวตกแต่งที่กำหนดเอง

หากต้องการสร้าง Decorator ให้ขยายคลาส NavEntryDecorator แล้วแทนที่เมธอดต่อไปนี้

  • decorate - Composable Lambda ที่เรียกใช้สำหรับแต่ละ NavEntry ใน Back Stack โดยจะรับ NavEntry เป็นพารามิเตอร์ ซึ่งช่วยให้คุณ สร้างออบเจ็กต์สถานะที่เชื่อมโยงกับ contentKey ของรายการ คุณสามารถ ใช้ CompositionLocalProvider เพื่อระบุการอ้างอิงไปยังเนื้อหาของรายการ นอกจากนี้ คุณยังครอบเนื้อหาด้วยฟังก์ชันที่ประกอบกันได้ หรือทริกเกอร์ผลข้างเคียงได้ด้วย คุณควรเรียกใช้ entry.Content() ภายในเมธอดนี้เสมอ
  • onPop - Callback ที่เรียกใช้เมื่อมีการนำ NavEntry ออกจาก Back Stack และออกจาก Composition โดยจะได้รับ contentKey ของ รายการที่นำออก ใช้ contentKey เพื่อระบุและล้างสถานะที่เชื่อมโยงกับรายการนั้น

ตัวอย่างต่อไปนี้จะขยายคลาส NavEntryDecorator เพื่อสร้าง Decorator ที่กำหนดเอง

// import androidx.navigation3.runtime.NavEntryDecorator
class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>(
    decorate = { entry ->
        Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated")
        entry.Content()
    },
    onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") }
)

หากตัวตกแต่งต้องเข้าถึงสถานะ ให้สร้างฟังก์ชันที่ประกอบกันได้ซึ่งสร้างสถานะดังกล่าว แล้วใช้ฟังก์ชันนั้นเพื่อสร้างตัวตกแต่ง ดูตัวอย่าง การติดตั้งใช้งานได้ที่ซอร์สโค้ดของ rememberSaveableStateHolderNavEntryDecorator ซึ่งจะสร้าง สถานะ - SaveableStateHolder - และใช้เพื่อสร้างตัวตกแต่ง

ตกแต่ง Back Stack

เมื่อสร้าง NavEntryDecorator แล้ว ให้ตกแต่งรายการใน สแต็กย้อนกลับด้วยวิธีใดวิธีหนึ่งต่อไปนี้

  • ใช้ rememberDecoratedNavEntries ฟังก์ชันนี้มีประโยชน์เมื่อคุณมี Back Stack หลายรายการ ซึ่งแต่ละรายการมีชุดตกแต่งของตัวเอง (ดูรายละเอียดเพิ่มเติมได้ที่สูตรโค้ดนี้) ฟังก์ชันจะแสดงรายการNavEntryที่ตกแต่งแล้ว ซึ่งคุณใช้กับ NavDisplay ได้
  • ระบุผู้ตกแต่งโดยตรงไปยัง NavDisplay โดยใช้พารามิเตอร์ entryDecorators NavDisplay เรียกใช้ rememberDecoratedNavEntries เบื้องหลัง และแสดงรายการที่ตกแต่งแล้ว

รวมเครื่องตกแต่งเริ่มต้น

Navigation 3 มี Decorator เริ่มต้นชื่อ SaveableStateHolderNavEntryDecorator ซึ่งช่วยให้NavEntryสามารถคงสถานะไว้ได้ แม้จะมีการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดการประมวลผล โดยจะห่อหุ้มเนื้อหา NavEntry ด้วย SaveableStateProvider ซึ่งจะช่วยให้การเรียก rememberSaveable ภายในเนื้อหา NavEntry ทำงานได้อย่างถูกต้อง

เว้นแต่ว่า Decorator ของคุณจะระบุ SaveableStateProvider คุณควร ใส่ SaveableStateHolderNavEntryDecorator เป็น Decorator ตัวแรกใน รายการ Decorator ที่ระบุ สร้างขึ้นโดยใช้ rememberSaveableStateHolderNavEntryDecorator

เช่น

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

ส่งผลลัพธ์โดยใช้ ResultEventBusNavEntryDecorator

ตั้งแต่ Navigation 3 1.2.0 เป็นต้นไป คุณสามารถใช้ ResultEventBusNavEntryDecorator เพื่อระบุ ResultEventBus ให้กับแต่ละ NavEntry โดยใช้ LocalResultEventBus องค์ประกอบภายใน

โดยค่าเริ่มต้น rememberResultEventBusNavEntryDecorator จะสร้างและจดจำอินสแตนซ์ ResultEventBus ของตัวเองภายในโดยใช้ rememberResultEventBus หากต้องการเข้าถึง Event Bus นอกลําดับชั้นของ Decorator (เช่น ที่การจัดโครงสร้างแอป ระดับบนสุด) คุณสามารถยก ResultEventBus ขึ้นได้โดยการเรียก rememberResultEventBus และส่งไปยัง rememberResultEventBusNavEntryDecorator(resultEventBus)

val resultEventBus = rememberResultEventBus()

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
    )
)

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการส่งและสังเกตผลลัพธ์ได้ที่ ส่งคืนผลลัพธ์

ควรใช้ Decorator เมื่อใด

ใช้ Decorator เพื่อทำสิ่งต่อไปนี้

  • สร้างการอ้างอิงสำหรับทุก NavEntry ใน Back Stack เช่น ViewModelStoreNavEntryDecorator จะสร้าง ViewModelStore สำหรับทุกๆ NavEntry
  • ส่งผลลัพธ์และสื่อสารระหว่างปลายทาง เช่น ResultEventBusNavEntryDecorator จะมี ResultEventBus ไปยังปลายทางใน Back Stack
  • กำหนดขอบเขตออบเจ็กต์ไปยัง NavEntry หลายรายการ เช่น หากต้องการแชร์ ViewModel ระหว่างรายการหลายรายการ
  • ดำเนินการเดียวกันกับ NavEntry หลายรายการ เช่น เพื่อดำเนินการ บันทึกการแก้ไขข้อบกพร่อง หรือการติดตามสำหรับแต่ละรายการ
  • ห่อหุ้ม NavEntry ด้วยฟังก์ชันที่ประกอบกันได้เดียวกัน
  • ล้างสถานะที่เชื่อมโยงกับ NavEntry เช่น เมื่อนำรายการออกจาก Back Stack ViewModelStoreNavEntryDecorator จะล้าง ViewModelStore ที่เชื่อมโยง

อย่าใช้ตัวตกแต่งเพื่อทำสิ่งต่อไปนี้

  • ส่งทรัพยากร Dependency ไปยัง NavEntry รายการเดียว
  • ระบุการอ้างอิงที่มีขอบเขตกว้างกว่า Back Stack

ในทั้ง 2 กรณีนี้ ให้ส่งการอ้างอิงโดยตรงเมื่อสร้าง NavEntry แทน

ดูตัวอย่างโค้ดเพิ่มเติมได้ที่ NavEntryDecorator