ธุรกรรมใน Fragment

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

คุณสามารถบันทึกธุรกรรมแต่ละรายการลงในสแต็กแบ็กสแต็กที่จัดการโดย FragmentManager ซึ่งช่วยให้ผู้ใช้สามารถย้อนกลับผ่าน การเปลี่ยนแปลงส่วนย่อย - คล้ายกับการย้อนกลับไปยังกิจกรรมต่างๆ

คุณสามารถรับอินสแตนซ์ของ FragmentTransaction ได้จาก FragmentManager ด้วยการเรียก beginTransaction() ดังที่ปรากฏในตัวอย่างต่อไปนี้:

Kotlin

val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

การโทรครั้งสุดท้ายในแต่ละ FragmentTransaction ต้องทำธุรกรรม สัญญาณการโทร commit() ไปยัง FragmentManager ว่าการดำเนินการทั้งหมด เพิ่มลงในธุรกรรมแล้ว

Kotlin

val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager.commit {
    // Add operations here
}

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// Add operations here

fragmentTransaction.commit();

อนุญาตให้เรียงลำดับการเปลี่ยนแปลงสถานะส่วนย่อยใหม่

FragmentTransaction แต่ละรายการควรใช้ setReorderingAllowed(true):

Kotlin

supportFragmentManager.commit {
    ...
    setReorderingAllowed(true)
}

Java

FragmentManager fragmentManager = ...
fragmentManager.beginTransaction()
    ...
    .setReorderingAllowed(true)
    .commit();

สำหรับความเข้ากันได้ของลักษณะการทำงาน แฟล็กการจัดเรียงใหม่ไม่ได้เปิดใช้โดยค่าเริ่มต้น อย่างไรก็ตาม จําเป็นเพื่อให้ FragmentManager ทํางานได้อย่างถูกต้อง FragmentTransaction ของคุณ โดยเฉพาะเมื่อทำงานกับสแต็กด้านหลัง และแสดงภาพเคลื่อนไหวและการเปลี่ยนภาพ การเปิดใช้งานการทำเครื่องหมายจะทำให้มั่นใจว่า ธุรกรรมหลายรายการจะถูกดำเนินการร่วมกัน ส่วนย่อยที่เป็นสื่อกลาง (เช่น รายการที่เพิ่มแล้วแทนที่ทันที) ดำเนินการไม่สำเร็จ มีการเปลี่ยนแปลงวงจรหรือมีการดำเนินการภาพเคลื่อนไหวหรือการเปลี่ยนภาพ โปรดทราบว่า แฟล็กนี้จะส่งผลต่อทั้งการดำเนินการครั้งแรกของธุรกรรมและการย้อนกลับ การทำธุรกรรมกับ popBackStack()

การเพิ่มและนำส่วนย่อยออก

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

หากต้องการนำส่วนย่อยออกจากโฮสต์ ให้เรียก remove() การส่งผ่านในอินสแตนซ์ส่วนย่อยที่ดึงมาจากส่วนย่อย ผ่าน findFragmentById() หรือ findFragmentByTag() หากมีการเพิ่มมุมมองของส่วนย่อยลงในคอนเทนเนอร์ก่อนหน้านี้ มุมมองจะเป็น นำออกจากคอนเทนเนอร์ ณ จุดนี้ ย้ายส่วนย่อยที่นำออกแล้ว เป็นสถานะ DESTROYED

ใช้ replace() เพื่อแทนที่ส่วนย่อยที่มีอยู่ในคอนเทนเนอร์ด้วยอินสแตนซ์ของ คลาสส่วนย่อยใหม่ที่คุณให้ไว้ การโทรไปยัง replace() เทียบเท่ากับ การเรียก remove() ด้วยส่วนย่อยในคอนเทนเนอร์และเพิ่ม ลงในคอนเทนเนอร์เดียวกันนั้น

ข้อมูลโค้ดต่อไปนี้แสดงวิธีแทนที่ส่วนย่อยหนึ่งด้วยอีกส่วนหนึ่ง

Kotlin

// Create new fragment
val fragmentManager = // ...

// Create and commit a new transaction
fragmentManager.commit {
    setReorderingAllowed(true)
    // Replace whatever is in the fragment_container view with this fragment
    replace<ExampleFragment>(R.id.fragment_container)
}

Java

// Create new fragment and transaction
FragmentManager fragmentManager = ...
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setReorderingAllowed(true);

// Replace whatever is in the fragment_container view with this fragment
transaction.replace(R.id.fragment_container, ExampleFragment.class, null);

// Commit the transaction
transaction.commit();

ในตัวอย่างนี้ อินสแตนซ์ใหม่ของ ExampleFragment จะแทนที่ส่วนย่อย หากมี ซึ่งขณะนี้อยู่ในคอนเทนเนอร์เลย์เอาต์ที่ระบุโดย R.id.fragment_container

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

คอมมิตไม่พร้อมกัน

การโทร commit() ไม่ได้ทำธุรกรรมโดยทันที แต่ธุรกรรมจะเป็น ให้ทำงานในเธรด UI หลักทันทีที่สามารถทำได้ ถ้า แต่คุณสามารถโทรหา commitNow() เพื่อเรียกใช้ธุรกรรมส่วนย่อยบนเธรด UI ของคุณทันที

โปรดทราบว่า commitNow ไม่สามารถใช้งานร่วมกับ addToBackStack หรือ คุณสามารถเรียกใช้ FragmentTransactions ที่รอดำเนินการทั้งหมดที่ส่งโดย commit() ที่ยังไม่ได้เรียกใช้โดยโทรไปที่ executePendingTransactions() วิธีนี้เข้ากันได้กับ addToBackStack

สำหรับ Use Case ส่วนใหญ่ คุณแค่ต้องมี commit() เท่านั้น

ลำดับการดำเนินการมีความสำคัญ

ลำดับที่คุณดำเนินการภายใน FragmentTransaction เป็นสิ่งสำคัญ โดยเฉพาะอย่างยิ่งเมื่อใช้ setCustomAnimations() ช่วงเวลานี้ จะนำภาพเคลื่อนไหวที่ระบุไปใช้กับการดำเนินการส่วนย่อยทั้งหมดที่ ทำตามคำนั้น

Kotlin

supportFragmentManager.commit {
    setCustomAnimations(enter1, exit1, popEnter1, popExit1)
    add<ExampleFragment>(R.id.container) // gets the first animations
    setCustomAnimations(enter2, exit2, popEnter2, popExit2)
    add<ExampleFragment>(R.id.container) // gets the second animations
}

Java

getSupportFragmentManager().beginTransaction()
        .setCustomAnimations(enter1, exit1, popEnter1, popExit1)
        .add(R.id.container, ExampleFragment.class, null) // gets the first animations
        .setCustomAnimations(enter2, exit2, popEnter2, popExit2)
        .add(R.id.container, ExampleFragment.class, null) // gets the second animations
        .commit()

จำกัดวงจรของส่วนย่อย

FragmentTransactions อาจส่งผลต่อสถานะวงจรของผู้ใช้ได้ ส่วนย่อยที่เพิ่มเข้ามาภายในขอบเขตของธุรกรรม เมื่อสร้าง FragmentTransaction, setMaxLifecycle() กำหนดสถานะสูงสุดสำหรับส่วนย่อยที่ระบุ ตัวอย่างเช่น ViewPager2 ใช้ setMaxLifecycle() เพื่อจำกัดส่วนย่อยบนหน้าจอให้เป็นสถานะ STARTED

การแสดงและซ่อนมุมมองของส่วนย่อย

ใช้เมธอด FragmentTransaction show() และ hide() เพื่อแสดงหรือซ่อนมุมมองของส่วนย่อยที่เพิ่มลงในคอนเทนเนอร์ วิธีการเหล่านี้จะกำหนดการแสดงมุมมองของส่วนย่อยโดยไม่มีผลกระทบ วงจรของส่วนย่อย

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

การติดและแยกส่วน

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

attach() ระบบจะแนบส่วนย่อยที่ถูกปลดออกก่อนหน้านี้อีกครั้ง ซึ่งจะทำให้เกิดการสร้างลำดับชั้นการแสดงผลขึ้นมาใหม่ โดยแนบอยู่กับ UI และแสดงไว้

เมื่อ FragmentTransaction จัดว่าเป็นชุดการดำเนินการแบบอะตอมเดี่ยว การเรียกไปยังทั้ง detach และ attach บนอินสแตนซ์ Fragment เดียวกันใน ธุรกรรมเดียวกันยกเลิกกันได้อย่างมีประสิทธิภาพ ดังนั้นจึงหลีกเลี่ยง การทำลายและการสร้าง UI ของส่วนย่อยในทันที ใช้ ธุรกรรม คั่นด้วย executePendingOperations() หากใช้ commit() ถ้าต้องการถอดและแนบแฟรกเมนต์ใหม่ทันที