ธุรกรรมใน Fragment

ขณะรันไทม์ FragmentManager จะเพิ่ม นําออก แทนที่ และดําเนินการอื่นๆ กับข้อมูลโค้ดเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้ การเปลี่ยนแปลงส่วนย่อยแต่ละชุดที่คุณคอมมิตจะเรียกว่าธุรกรรม และคุณจะระบุสิ่งที่ต้องทำภายในธุรกรรมได้โดยใช้ 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();

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

การเพิ่มและนำข้อมูลโค้ดที่แยกส่วนออก

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

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

ใช้ replace() เพื่อแทนที่ Fragment ที่มีอยู่ในคอนเทนเนอร์ด้วยอินสแตนซ์ของ Fragment Class ใหม่ที่คุณให้ไว้ การเรียกใช้ 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

commit() เพียงพอแล้วสำหรับ Use Case ส่วนใหญ่

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

ลําดับที่คุณดําเนินการภายใน 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 methods show() และ hide() เพื่อแสดงและซ่อนมุมมองของข้อมูลโค้ดที่เพิ่มลงในคอนเทนเนอร์ วิธีการเหล่านี้จะตั้งค่าระดับการแชร์ของมุมมองของข้อมูลพร็อพเพอร์ตี้โดยไม่ส่งผลต่อวงจรชีวิตของข้อมูลพร็อพเพอร์ตี้

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

การแนบและถอดส่วนย่อย

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

วิธีการ attach() จะแนบส่วนที่แยกออกก่อนหน้านี้อีกครั้ง ซึ่งจะทําให้ระบบสร้างลําดับชั้นมุมมองขึ้นมาใหม่ แนบกับ UI และแสดง

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