ทําความเข้าใจและใช้งานพื้นฐาน

การนำทางอธิบายวิธีที่ผู้ใช้ไปยังส่วนต่างๆ ของแอป โดยผู้ใช้โต้ตอบกับองค์ประกอบ UI โดยปกติแล้วด้วยการแตะหรือคลิก และแอปจะตอบสนองด้วยการแสดงเนื้อหาใหม่ หากต้องการกลับไปที่เนื้อหาก่อนหน้า ผู้ใช้จะใช้ท่าทางสัมผัสย้อนกลับหรือแตะปุ่มย้อนกลับ

การสร้างรูปแบบสถานะการนำทาง

วิธีจำลองลักษณะการทำงานนี้ที่สะดวกคือการใช้กองเนื้อหา เมื่อผู้ใช้เลื่อนไปข้างหน้าไปยังเนื้อหาใหม่ ระบบจะดันเนื้อหานั้นไว้ที่ด้านบนของกอง เมื่อผู้ใช้ย้อนกลับจากเนื้อหานั้น ระบบจะยกเนื้อหานั้นออกจากกองและแสดงเนื้อหาก่อนหน้า ในบริบทการนําทาง กองนี้มักเรียกว่ากองซ้อนย้อนกลับ เนื่องจากแสดงถึงเนื้อหาที่ผู้ใช้ย้อนกลับได้

ปุ่มการดำเนินการของแป้นพิมพ์เสมือน (ไอคอนเครื่องหมายถูก) วงกลมสีแดง
รูปที่ 1 แผนภาพแสดงการเปลี่ยนแปลงของกองซ้อนที่ย้อนกลับตามเหตุการณ์การนําทางของผู้ใช้

สร้างกองซ้อนที่ย้อนกลับ

ในการนำทาง 3 สแต็กย้อนกลับไม่มีเนื้อหา แต่จะมีการอ้างอิงเนื้อหาที่เรียกว่าคีย์ คีย์อาจเป็นประเภทใดก็ได้ แต่มักจะเป็นคลาสข้อมูลที่จัดเก็บเป็นอนุกรมได้ง่ายๆ การใช้ข้อมูลอ้างอิงแทนเนื้อหามีประโยชน์ดังต่อไปนี้

  • ไปยังส่วนต่างๆ ได้ง่ายโดยกดแป้นลงในกองที่ซ้อนกัน
  • ตราบใดที่คีย์เป็นคีย์ที่ซีเรียลไลซ์ได้ ระบบจะบันทึกกองซ้อนย้อนกลับไปยังพื้นที่เก็บข้อมูลถาวรได้ ซึ่งจะช่วยให้กองซ้อนย้อนกลับอยู่รอดได้แม้จะมีการเปลี่ยนแปลงการกําหนดค่าและกระบวนการสิ้นสุด การดำเนินการนี้สำคัญเนื่องจากผู้ใช้คาดหวังว่าจะออกจากแอปของคุณ แล้วกลับมาใช้แอปในภายหลัง และกลับมาดูเนื้อหาต่อจากเดิมโดยที่เนื้อหานั้นยังแสดงอยู่ ดูข้อมูลเพิ่มเติมที่บันทึกกองซ้อนที่ย้อนกลับ

แนวคิดสําคัญใน Navigation 3 API คือคุณเป็นเจ้าของกองซ้อนที่ย้อนกลับ ไลบรารี

  • คาดว่ากองซ้อนที่ซ้อนกลับจะเป็น List<T> ที่สำรองสถานะภาพรวม โดยที่ T คือประเภทของกองซ้อนที่ซ้อนกลับ keys คุณสามารถใช้ Any หรือจะระบุคีย์ของคุณเองที่มีการกำหนดประเภทที่เข้มงวดมากขึ้นก็ได้ เมื่อเห็นคำว่า "push" หรือ "pop" การใช้งานพื้นฐานคือการเพิ่มหรือนำรายการออกจากท้ายรายการ
  • ตรวจสอบกองซ้อนที่ย้อนกลับและแสดงสถานะใน UI โดยใช้ NavDisplay

ตัวอย่างต่อไปนี้แสดงวิธีสร้างคีย์และกองซ้อนที่ย้อนกลับ รวมถึงแก้ไขกองซ้อนที่ย้อนกลับเพื่อตอบสนองต่อเหตุการณ์การนําทางของผู้ใช้

// Define keys that will identify content
data object ProductList
data class ProductDetail(val id: String)

@Composable
fun MyApp() {

    // Create a back stack, specifying the key the app should start with
    val backStack = remember { mutableStateListOf<Any>(ProductList) }

    // Supply your back stack to a NavDisplay so it can reflect changes in the UI
    // ...more on this below...

    // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state
    backStack.add(ProductDetail(id = "ABC"))

    // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state
    backStack.removeLastOrNull()
}

แก้ปัญหาเกี่ยวกับคีย์ของเนื้อหา

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

NavEntry ยังมีข้อมูลเมตา ซึ่งเป็นข้อมูลเกี่ยวกับเนื้อหาด้วย ออบเจ็กต์คอนเทนเนอร์ เช่น NavDisplay สามารถอ่านข้อมูลเมตานี้ได้เพื่อช่วยในการตัดสินใจว่าจะแสดงเนื้อหาของ NavEntry อย่างไร เช่น คุณสามารถใช้ข้อมูลเมตาเพื่อลบล้างภาพเคลื่อนไหวเริ่มต้นของ NavEntry ที่เฉพาะเจาะจงได้ NavEntry metadata คือแผนที่ของคีย์ String กับค่า Any ซึ่งจัดเก็บข้อมูลได้หลากหลาย

หากต้องการแปลง key เป็น NavEntry ให้สร้าง entryProvider นี่คือฟังก์ชันที่ยอมรับ key และแสดงผล NavEntry สำหรับ key นั้น โดยปกติจะกำหนดเป็นพารามิเตอร์ lambda เมื่อสร้าง NavDisplay

การสร้าง entryProvider มี 2 วิธี ได้แก่ การสร้างฟังก์ชัน Lambda โดยตรง หรือใช้ entryProvider DSL

สร้างฟังก์ชัน entryProvider โดยตรง

โดยทั่วไปคุณสร้างฟังก์ชัน entryProvider โดยใช้คำสั่ง when โดยมีสาขาสำหรับคีย์แต่ละรายการ

entryProvider = { key ->
    when (key) {
        is ProductList -> NavEntry(key) { Text("Product List") }
        is ProductDetail -> NavEntry(
            key,
            metadata = mapOf("extraDataKey" to "extraDataValue")
        ) { Text("Product ${key.id} ") }

        else -> {
            NavEntry(Unit) { Text(text = "Invalid Key: $it") }
        }
    }
}

ใช้ entryProvider DSL

entryProvider DSL สามารถลดความซับซ้อนของฟังก์ชัน LAMBDA ได้โดยที่คุณไม่ต้องทดสอบกับคีย์แต่ละประเภทและสร้าง NavEntry สำหรับแต่ละประเภท ใช้ฟังก์ชันบิลเดอร์ entryProvider รวมถึงมีลักษณะการทำงานเริ่มต้นสำรอง (แสดงข้อผิดพลาด) หากไม่พบคีย์

entryProvider = entryProvider {
    entry<ProductList> { Text("Product List") }
    entry<ProductDetail>(
        metadata = mapOf("extraDataKey" to "extraDataValue")
    ) { key -> Text("Product ${key.id} ") }
}

โปรดสังเกตสิ่งต่อไปนี้จากตัวอย่าง

  • entry ใช้เพื่อกำหนด NavEntry ที่มีประเภทและเนื้อหาแบบคอมโพสิเบิลที่ระบุ
  • entry ยอมรับพารามิเตอร์ metadata เพื่อตั้งค่า NavEntry.metadata

แสดงกองซ้อนที่ย้อนกลับ

กองซ้อนที่ย้อนกลับแสดงสถานะการนําทางของแอป เมื่อใดก็ตามที่กองซ้อนที่แสดงอยู่เบื้องหลังมีการเปลี่ยนแปลง UI ของแอปควรแสดงสถานะกองซ้อนที่แสดงอยู่เบื้องหลังใหม่ ในการนำทาง 3 NavDisplay จะสังเกตการณ์กองซ้อนที่ย้อนกลับและอัปเดต UI ให้สอดคล้องกัน สร้าง ด้วยพารามิเตอร์ต่อไปนี้

  • กองซ้อนที่ย้อนกลับ - ข้อมูลนี้ควรเป็นประเภท SnapshotStateList<T> โดยที่ T คือประเภทของคีย์กองซ้อนที่ย้อนกลับ List เป็นสิ่งที่สังเกตได้เพื่อให้เรียกใช้การจัดองค์ประกอบใหม่ของ NavDisplay เมื่อมีการเปลี่ยนแปลง
  • entryProvider เพื่อแปลงคีย์ในกองซ้อนที่ซ้อนกันไว้เป็น NavEntry
  • (ไม่บังคับ) ระบุ Lambda ให้กับพารามิเตอร์ onBack เหตุการณ์นี้จะเกิดขึ้นเมื่อผู้ใช้เรียกเหตุการณ์ "กลับ"

ตัวอย่างต่อไปนี้แสดงวิธีสร้าง NavDisplay

data object Home
data class Product(val id: String)

@Composable
fun NavExample() {

    val backStack = remember { mutableStateListOf<Any>(Home) }

    NavDisplay(
        backStack = backStack,
        onBack = { backStack.removeLastOrNull() },
        entryProvider = { key ->
            when (key) {
                is Home -> NavEntry(key) {
                    ContentGreen("Welcome to Nav3") {
                        Button(onClick = {
                            backStack.add(Product("123"))
                        }) {
                            Text("Click to navigate")
                        }
                    }
                }

                is Product -> NavEntry(key) {
                    ContentBlue("Product ${key.id} ")
                }

                else -> NavEntry(Unit) { Text("Unknown route") }
            }
        }
    )
}

โดยค่าเริ่มต้น NavDisplay จะแสดง NavEntry ที่ด้านบนสุดในกองที่ซ้อนกันอยู่ด้านหลังในเลย์เอาต์แบบแผงเดียว ไฟล์บันทึกเสียงต่อไปนี้แสดงแอปนี้ที่ทำงานอยู่

ลักษณะการทำงานเริ่มต้นของ `NavDisplay` ที่มีปลายทาง 2 แห่ง
รูปที่ 2 NavDisplay ลักษณะการทำงานเริ่มต้นที่มีปลายทาง 2 แห่ง

สรุปข้อมูลทั้งหมด

แผนภาพต่อไปนี้แสดงการไหลของข้อมูลระหว่างออบเจ็กต์ต่างๆ ในการนำทาง 3

ภาพแสดงการไหลของข้อมูลระหว่างวัตถุต่างๆ ในการนำทาง 3
รูปที่ 3 แผนภาพแสดงเส้นทางที่ข้อมูลไหลผ่านออบเจ็กต์ต่างๆ ในการนำทาง 3
  1. เหตุการณ์การนําทางจะเริ่มต้นการเปลี่ยนแปลง ระบบจะเพิ่มหรือนําคีย์ออกจากกองซ้อนย้อนกลับเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้

  2. การเปลี่ยนแปลงสถานะกองซ้อนด้านหลังจะทริกเกอร์การดึงข้อมูลเนื้อหา NavDisplay (คอมโพสิชันที่แสดงผลกองซ้อนด้านหลัง) จะสังเกตกองซ้อนด้านหลัง ในการกำหนดค่าเริ่มต้น รายการสแต็กย้อนกลับบนสุดจะแสดงในเลย์เอาต์แผงเดียว เมื่อคีย์ด้านบนในกองซ้อนที่ซ้อนกันจะเปลี่ยนแปลง NavDisplay จะใช้คีย์นี้เพื่อขอเนื้อหาที่เกี่ยวข้องจากผู้ให้บริการรายการ

  3. ผู้ให้บริการข้อมูลเป็นผู้จัดหาเนื้อหา ผู้ให้บริการรายการคือฟังก์ชันที่แปลงคีย์เป็น NavEntry เมื่อได้รับคีย์จาก NavDisplay ผู้ให้บริการรายการจะระบุ NavEntry ที่เชื่อมโยง ซึ่งมีทั้งคีย์และเนื้อหา

  4. เนื้อหาแสดงขึ้น NavDisplay จะรับ NavEntry และแสดงเนื้อหา