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

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

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

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

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

สร้างสแต็กย้อนกลับ

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

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

แนวคิดสำคัญใน Navigation 3 API คือคุณเป็นเจ้าของ Back Stack ไลบรารี

  • คาดหวังว่า Back Stack จะเป็น List<T> ที่สำรองข้อมูลสถานะสแนปชอต โดยที่ T คือประเภทของ keys Back Stack คุณสามารถใช้ 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 ให้สร้างผู้ให้บริการรายการ นี่คือฟังก์ชันที่รับ key และแสดงผล NavEntry สำหรับ key นั้น โดยปกติจะกำหนดเป็นพารามิเตอร์ Lambda เมื่อสร้าง NavDisplay

คุณสร้าง Entry Provider ได้ 2 วิธี ไม่ว่าจะสร้างฟังก์ชัน Lambda โดยตรง หรือใช้ DSL ของ entryProvider

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

โดยปกติแล้ว คุณจะสร้างฟังก์ชัน Entry Provider โดยใช้คำสั่ง 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") }
        }
    }
}

ใช้ DSL ของ entryProvider

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

แสดงสแต็กย้อนกลับ

Back Stack แสดงสถานะการนำทางของแอป เมื่อใดก็ตามที่สแต็กย้อนกลับ มีการเปลี่ยนแปลง UI ของแอปควรแสดงสถานะสแต็กย้อนกลับใหม่ ใน Navigation 3, a 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

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

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

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

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