ขณะรันไทม์ FragmentManager
จะเพิ่ม นําออก แทนที่ และดําเนินการอื่นๆ กับข้อมูลโค้ดเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้ การเปลี่ยนแปลงส่วนย่อยแต่ละชุดที่คุณคอมมิตจะเรียกว่าธุรกรรม และคุณจะระบุสิ่งที่ต้องทำภายในธุรกรรมได้โดยใช้ API ที่คลาส FragmentTransaction
มีให้ คุณจัดกลุ่มการดำเนินการหลายอย่างไว้ในธุรกรรมเดียวได้ เช่น ธุรกรรมหนึ่งอาจเพิ่มหรือแทนที่ส่วนย่อยหลายรายการได้ การจัดกลุ่มนี้อาจมีประโยชน์เมื่อคุณมีส่วนย่อยหลายๆ ข้างเคียงแสดงในหน้าจอเดียวกัน เช่น แยกมุมมอง
คุณสามารถบันทึกธุรกรรมแต่ละรายการลงในกองซ้อนที่ย้อนกลับซึ่งจัดการโดย FragmentManager
ซึ่งจะช่วยให้ผู้ใช้ไปยังส่วนต่างๆ ของการเปลี่ยนแปลงได้ย้อนกลับ คล้ายกับการไปยังส่วนต่างๆ ของกิจกรรมย้อนกลับ
คุณรับอินสแตนซ์ของ FragmentTransaction
จาก FragmentManager
ได้ด้วยการเรียกใช้ beginTransaction()
ดังตัวอย่างต่อไปนี้
val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()
FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
การเรียกใช้สุดท้ายใน FragmentTransaction
แต่ละรายการต้องทําธุรกรรม
สัญญาณการโทร commit()
ไปยัง FragmentManager
ที่ระบุว่ามีการเพิ่มการดำเนินการทั้งหมดลงในธุรกรรมแล้ว
val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager.commit {
// Add operations here
}
FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Add operations here
fragmentTransaction.commit();
อนุญาตให้จัดเรียงการเปลี่ยนแปลงสถานะรายการใหม่
FragmentTransaction
แต่ละรายการควรใช้ setReorderingAllowed(true)
:
supportFragmentManager.commit {
...
setReorderingAllowed(true)
}
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()
ที่มีข้อมูลโค้ดในคอนเทนเนอร์และเพิ่มข้อมูลโค้ดใหม่ลงในคอนเทนเนอร์เดียวกัน
ข้อมูลโค้ดต่อไปนี้แสดงวิธีแทนที่ข้อมูลโค้ดหนึ่งด้วยอีกข้อมูลโค้ดหนึ่ง
// 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)
}
// 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()
วิธีนี้จะใช้ภาพเคลื่อนไหวที่ระบุกับการดำเนินการกับข้อมูลโค้ดทุกรายการที่ตามมา
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
}
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()
หากต้องการถอดออกแล้วแนบอีกครั้งทันที