การนำทางและกลุ่มย้อนกลับ

NavController มี "Back Stack" ที่มีปลายทางที่ผู้ใช้ เยี่ยมชมแล้ว ขณะที่ผู้ใช้ไปยังหน้าจอต่างๆ ในแอป NavController เพิ่มและนำปลายทางไปยังและออกจากแบ็กสแต็ก

ในกองซ้อน กองกลับจะเป็นแบบ "เริ่มก่อนเลย" โครงสร้างข้อมูล ดังนั้น NavController จะพุชรายการไปยังและแสดงรายการจากด้านบนของ สแต็ก

ลักษณะการทำงานพื้นฐาน

ต่อไปนี้เป็นข้อเท็จจริงสำคัญที่คุณควรพิจารณาเกี่ยวกับการทำงานของระบบด้านหลัง กอง:

  • ปลายทางแรก: เมื่อผู้ใช้เปิดแอป NavController ดันจุดหมายแรกไปที่ด้านบนสุดของกลุ่มสำรอง
  • การดันไปที่กอง: การพุชแต่ละครั้งที่เรียกใช้ NavController.navigate() ปลายทางที่ระบุไปยังด้านบนของกลุ่ม
  • ปลายทางยอดนิยม: การแตะขึ้นหรือกลับสายเรียกเข้า NavController.navigateUp() และ NavController.popBackStack() ตามลำดับ โฆษณา Shopping จะแสดงที่จุดหมายยอดนิยม โปรดดู หน้าหลักการการนำทางเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่าง ระหว่างขึ้นและย้อนกลับ

จอเล็ก

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

กลับไปยังจุดหมายที่เฉพาะเจาะจง

คุณยังใช้ popBackStack() เพื่อนำทางไปยังจุดหมายที่ต้องการได้ด้วย สิ่งต้องทำ ให้ใช้โอเวอร์โหลดรายการหนึ่ง มีวิธีมากมายที่ให้คุณส่งผ่าน เช่น จำนวนเต็ม id หรือสตริง route การทำงานหนักเกินไปใช้เวลา ผู้ใช้ไปยังปลายทางที่เชื่อมโยงกับตัวระบุที่กำหนด โดยเฉพาะอย่างยิ่ง พวกเขาก็ทำให้ทุกอย่างวางอยู่บนกองเหนือจุดหมายนั้น

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

ลองดูตัวอย่างสั้นๆ นี้

navController.popBackStack(R.id.destinationId, true)

ตรงนี้ NavController จะแสดงกลับไปยังปลายทางด้วยรหัสจำนวนเต็ม destinationId เนื่องจากค่าของอาร์กิวเมนต์ inclusive คือ true ค่า นอกจากนี้ NavController ยังแสดงปลายทางที่ระบุจากสแต็กด้านหลังด้วย

จัดการป๊อปอัปที่ล้มเหลว

เมื่อ popBackStack() แสดงผล false การเรียกครั้งต่อๆ มาไปยัง NavController.getCurrentDestination() แสดงผล null ซึ่งหมายความว่าแอป ดึงจุดหมายสุดท้ายออกนอกกลุ่ม ในกรณีนี้ ผู้ใช้จะเห็นเฉพาะ หน้าจอว่างเปล่า

ซึ่งอาจเกิดขึ้นในกรณีต่อไปนี้

  • popBackStack() ไม่แสดงรายการใดๆ จากกองเลย
  • popBackStack() แสดงปลายทางออกจากกองแบ็กและกองซ้อนอยู่ ว่างเปล่าแล้ว

หากต้องการแก้ไขปัญหานี้ คุณต้องไปยังปลายทางใหม่หรือโทรหา finish() กิจกรรมของคุณเพื่อให้สิ้นสุด ข้อมูลโค้ดต่อไปนี้แสดงให้เห็นสิ่งต่อไปนี้

Kotlin

...

if (!navController.popBackStack()) {
    // Call finish() on your Activity
    finish()
}

Java

...

if (!navController.popBackStack()) {
    // Call finish() on your Activity
    finish();
}

ป๊อปอัปไปยังจุดหมาย

ในการนำปลายทางออกจากแบ็กสแต็กเมื่อนำทางจากปลายทางหนึ่ง ในอีกฟังก์ชันหนึ่ง เพิ่มอาร์กิวเมนต์ popUpTo() ลงในฟังก์ชัน navigate() ที่เกี่ยวข้อง การโทร popUpTo() สั่งให้ไลบรารีการนำทางนำจุดหมายบางรายการออก จากกองหลังโดยเป็นส่วนหนึ่งของการเรียกไปยัง navigate() ค่าพารามิเตอร์คือ ตัวระบุของปลายทาง ไว้ในกลุ่มแบ็กสแต็ก ตัวระบุอาจเป็น จำนวนเต็ม id หรือสตริง route

คุณใส่อาร์กิวเมนต์สำหรับพารามิเตอร์ inclusive ที่มีค่าเป็น true ได้ เพื่อระบุว่าปลายทางที่คุณระบุใน popUpTo() ควร กลับกองซ้อน

หากต้องการใช้วิธีนี้แบบเป็นโปรแกรม โปรดส่ง popUpTo() ไปยัง navigate() ในฐานะส่วนหนึ่งของ ตั้งค่า NavOptions กับ inclusive เป็น true วิธีนี้ใช้ได้ทั้งในเวอร์ชัน Compose และ ยอดดู

บันทึกสถานะเมื่อป๊อปอัปขึ้นมา

เมื่อคุณใช้ popUpTo เพื่อนำทางไปยังปลายทาง คุณสามารถเลือกบันทึก Back Stack และสถานะของปลายทางทั้งหมดปรากฏขึ้นจาก Back Stack คุณสามารถ จากนั้นคืนค่าแบ็กสแต็กและปลายทางเมื่อไปยังปลายทางนั้น ในภายหลัง ซึ่งจะช่วยให้คุณสามารถรักษาสถานะสำหรับปลายทางที่ระบุและ แบ็กสแต็กหลายตัว

หากต้องการดำเนินการแบบเป็นโปรแกรม ให้ระบุ saveState = true เมื่อเพิ่ม popUpTo ลงใน ตัวเลือกการนำทางต่างๆ

คุณยังสามารถระบุ restoreState = true ในตัวเลือกการนำทางเพื่อ จะคืนค่าแบ็กสแต็กและสถานะที่เชื่อมโยงกับ ปลายทาง

เช่น

navController.navigate(
    route = route,
    navOptions =  navOptions {
        popUpTo<A>{ saveState = true }
        restoreState = true
    }
)

หากต้องการเปิดใช้การบันทึกและคืนค่าสถานะใน XML ให้กำหนด popUpToSaveState เป็น true และ restoreState เป็น true ตามลำดับใน action ที่เกี่ยวข้อง

ตัวอย่าง XML

นี่คือตัวอย่างของ popUpTo ใน XML ที่ใช้การดำเนินการ

<action
  android:id="@+id/action_a_to_b"
  app:destination="@id/b"
  app:popUpTo="@+id/a"
  app:popUpToInclusive="true"
  app:restoreState=”true”
  app:popUpToSaveState="true"/>

ตัวอย่างการเขียน

ตัวอย่างต่อไปนี้คือตัวอย่างทั้งหมดใน Compose:

@Composable
fun MyAppNavHost(
    modifier: Modifier = Modifier,
    navController: NavHostController = rememberNavController(),
    startDestination: Any = A
) {
    NavHost(
        modifier = modifier,
        navController = navController,
        startDestination = startDestination
    ) {
        composable<A> {
            DestinationA(
                onNavigateToB = {
                // Pop everything up to, and including, the A destination off
                // the back stack, saving the back stack and the state of its
                // destinations.
                // Then restore any previous back stack state associated with
                // the B destination.
                // Finally navigate to the B destination.
                    navController.navigate(route = B) {
                        popUpTo<A> {
                            inclusive = true
                            saveState = true
                        }
                        restoreState = true
                    }
                },
            )
        }
        composable<B> { DestinationB(/* ... */) }
    }
}

@Composable
fun DestinationA(onNavigateToB: () -> Unit) {
    Button(onClick = onNavigateToB) {
        Text("Go to A")
    }
}

คุณสามารถเปลี่ยนวิธีโทรหา NavController.navigate() ได้ละเอียดยิ่งขึ้นใน วิธีต่อไปนี้

// Pop everything up to the destination_a destination off the back stack before
// navigating to the "destination_b" destination
navController.navigate("destination_b") {
    popUpTo("destination_a")
}

// Pop everything up to and including the "destination_a" destination off
// the back stack before navigating to the "destination_b" destination
navController.navigate("destination_b") {
    popUpTo("destination_a") { inclusive = true }
}

// Navigate to the "search” destination only if we’re not already on
// the "search" destination, avoiding multiple copies on the top of the
// back stack
navController.navigate("search") {
    launchSingleTop = true
}

สำหรับข้อมูลทั่วไปเกี่ยวกับตัวเลือกการส่งไปยัง NavController.navigate() โปรดดูที่ คำแนะนำเกี่ยวกับการนำทางด้วยตัวเลือก

ป๊อปโดยใช้การดำเนินการ

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

อ่านเพิ่มเติม

สำหรับข้อมูลเพิ่มเติม โปรดอ่านหน้าต่อไปนี้

  • การนำทางแบบวนรอบ: ดูวิธีหลีกเลี่ยงการทำให้เต็มจอ ในกรณีที่ขั้นตอนการนำทางเป็นวงกลม
  • ปลายทางของกล่องโต้ตอบ: อ่านเกี่ยวกับวิธีที่ปลายทางของกล่องโต้ตอบแสดงขึ้น ข้อควรพิจารณาเป็นพิเศษเกี่ยวกับวิธีจัดการแบ็กกราวด์