การทำงานต่างๆ ของระบบ Android อาจส่งผลต่อสถานะของส่วนย่อยได้ เฟรมเวิร์ก Android จะบันทึกและกู้คืนข้อมูลแฟรกเมนต์และกองซ้อนที่ซ้อนกันโดยอัตโนมัติเพื่อให้มั่นใจว่าระบบจะบันทึกสถานะของผู้ใช้ ดังนั้นคุณต้องตรวจสอบว่าได้บันทึกและคืนค่าข้อมูลในส่วนย่อยแล้วเช่นกัน
ตารางต่อไปนี้แสดงการดำเนินการที่ทำให้ข้อมูลโค้ดโค้ดเสียสถานะ รวมถึงระบุว่าสถานะประเภทต่างๆ จะยังคงอยู่หลังจากการเปลี่ยนแปลงเหล่านั้นหรือไม่ ประเภทสถานะที่กล่าวถึงในตารางมีดังนี้
- ตัวแปร: ตัวแปรภายในของข้อมูลโค้ด
- สถานะมุมมอง: ข้อมูลใดก็ตามที่มุมมองอย่างน้อย 1 รายการเป็นเจ้าของในส่วนข้อมูล
- SavedState: ข้อมูลที่มีอยู่ในอินสแตนซ์ของ Fragment นี้ซึ่งควรบันทึกใน
onSaveInstanceState()
- NonConfig: ข้อมูลที่ดึงมาจากแหล่งที่มาภายนอก เช่น เซิร์ฟเวอร์หรือที่เก็บข้อมูลในเครื่อง หรือข้อมูลที่ผู้ใช้สร้างขึ้นซึ่งส่งไปยังเซิร์ฟเวอร์เมื่อคอมมิตแล้ว
บ่อยครั้งที่ตัวแปรได้รับการปฏิบัติเช่นเดียวกับ SavedState แต่ตารางต่อไปนี้จะแยกความแตกต่างระหว่าง 2 รายการนี้เพื่อแสดงให้เห็นผลของการดำเนินการต่างๆ กับแต่ละรายการ
การดำเนินการ | ตัวแปร | ดูสถานะ | SavedState | ไม่มีการกำหนดค่า |
---|---|---|---|---|
เพิ่มลงในกองซ้อนที่ซ้อนกัน | ✓ | ✓ | x | ✓ |
การเปลี่ยนแปลงการกําหนดค่า | x | ✓ | ✓ | ✓ |
การสิ้นสุดการประมวลผล/การสร้างใหม่ | x | ✓ | ✓ | ✓* |
Removed not added to back stack | x | x | x | x |
โฮสต์เสร็จแล้ว | x | x | x | x |
* สามารถเก็บรักษาสถานะ NonConfig ไว้ตลอดกระบวนการสูงสุดได้โดยใช้โมดูล "Saved State" สำหรับ ViewModel
ตารางที่ 1: การดำเนินการที่ทำลายข้อมูลในรายการต่างๆ ของรายการย่อยและผลที่การดำเนินการเหล่านั้นมีต่อสถานะประเภทต่างๆ
เรามาดูตัวอย่างที่เจาะจงกัน พิจารณาหน้าจอที่สร้างสตริงแบบสุ่ม แสดงใน TextView
และมีตัวเลือกให้แก้ไขสตริงก่อนที่จะส่งให้เพื่อน
ในตัวอย่างนี้ สมมติว่าเมื่อผู้ใช้กดปุ่มแก้ไข แอปจะแสดงมุมมอง EditText
ที่ผู้ใช้แก้ไขข้อความได้ หากผู้ใช้คลิกยกเลิก ระบบควรล้างมุมมอง EditText
และตั้งค่าระดับการมองเห็นเป็น View.GONE
หน้าจอดังกล่าวอาจต้องจัดการข้อมูล 4 รายการเพื่อให้ได้รับประสบการณ์การใช้งานที่ราบรื่น
ข้อมูล | ประเภท | ประเภทสถานะ | คำอธิบาย |
---|---|---|---|
seed |
Long |
NonConfig | เมล็ดพันธุ์ที่ใช้สําหรับสร้างการกระทําดีใหม่แบบสุ่ม สร้างขึ้นเมื่อสร้าง ViewModel |
randomGoodDeed |
String |
SavedState + ตัวแปร | สร้างขึ้นเมื่อสร้างข้อมูลโค้ดครั้งแรก
ระบบจะบันทึก randomGoodDeed ไว้เพื่อให้ผู้ใช้เห็นการกระทำดีแบบสุ่มแบบเดียวกันหลังจากที่กระบวนการเสียชีวิตและการสันทนาการไปแล้ว |
isEditing |
Boolean |
SaveState + ตัวแปร | ตั้งค่า Flag บูลีนเป็น true เมื่อผู้ใช้เริ่มแก้ไข
isEditing จะถูกบันทึกไว้เพื่อให้แน่ใจว่าส่วนการแก้ไขของหน้าจอจะยังคงมองเห็นได้เมื่อสร้างข้อมูลโค้ดโค้ดอีกครั้ง |
ข้อความที่แก้ไข | Editable |
สถานะการดู (เป็นของ EditText ) |
ข้อความที่แก้ไขในมุมมอง EditText
มุมมอง EditText จะบันทึกข้อความนี้เพื่อไม่ให้การเปลี่ยนแปลงที่อยู่ระหว่างดำเนินการของผู้ใช้สูญหายไป |
ตารางที่ 2: ระบุว่าแอปสร้างข้อความแบบสุ่มต้องจัดการ
ส่วนต่อไปนี้อธิบายวิธีจัดการสถานะของข้อมูลอย่างถูกต้องผ่านการดำเนินการแบบทำลาย
ดูสถานะ
มุมมองมีหน้าที่รับผิดชอบในการจัดการสถานะของตนเอง เช่น เมื่อมุมมองยอมรับอินพุตของผู้ใช้ มุมมองมีหน้าที่รับผิดชอบในการบันทึกและกู้คืนอินพุตนั้นเพื่อจัดการการเปลี่ยนแปลงการกําหนดค่า มุมมองทั้งหมดที่เฟรมเวิร์ก Android มีให้จะใช้ onSaveInstanceState()
และ onRestoreInstanceState()
ของตัวเอง คุณจึงไม่ต้องจัดการสถานะมุมมองภายในฟragment
ตัวอย่างเช่น ในสถานการณ์สมมติก่อนหน้านี้ ระบบจะเก็บสตริงที่แก้ไขไว้ใน EditText
EditText
จะทราบค่าของข้อความที่แสดง รวมถึงรายละเอียดอื่นๆ เช่น ต้นและท้ายของข้อความที่เลือก
ข้อมูลพร็อพเพอร์ตี้จำเป็นต้องมีรหัสเพื่อคงสถานะไว้ รหัสนี้ต้องไม่ซ้ำกันภายในกลุ่มและลําดับชั้นมุมมองของกลุ่ม ข้อมูลพร็อพเพอร์ตี้ที่ไม่มีรหัสจะเก็บสถานะไว้ไม่ได้
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
ดังที่กล่าวไว้ในตารางที่ 1 มุมมองจะบันทึกและกู้คืนViewState
ผ่านการดำเนินการทั้งหมดที่ไม่ได้นำข้อมูลโค้ดย่อยออกหรือทำลายโฮสต์
SavedState
ข้อมูลโค้ดจะมีหน้าที่จัดการสถานะแบบไดนามิกจํานวนเล็กน้อยซึ่งสําคัญต่อวิธีทํางานของข้อมูลโค้ด คุณสามารถเก็บรักษาข้อมูลที่ซีเรียลไลซ์ได้ง่ายโดยใช้ Fragment.onSaveInstanceState(Bundle)
ข้อมูลที่คุณใส่ไว้ในแพ็กเกจจะยังคงอยู่แม้มีการเปลี่ยนแปลงการกําหนดค่า รวมถึงเมื่อกระบวนการสิ้นสุดและสร้างใหม่ และข้อมูลดังกล่าวจะอยู่ในเมธอด onCreate(Bundle)
, onCreateView(LayoutInflater, ViewGroup, Bundle)
และ onViewCreated(View, Bundle)
ของข้อมูลโค้ดActivity.onSaveInstanceState(Bundle)
จากตัวอย่างก่อนหน้านี้ randomGoodDeed
คือการกระทำที่แสดงต่อผู้ใช้ และ isEditing
คือ Flag เพื่อระบุว่าจะแสดงหรือซ่อน EditText
สถานะที่บันทึกไว้นี้ควรคงอยู่โดยใช้ onSaveInstanceState(Bundle)
ตามที่แสดงในตัวอย่างต่อไปนี้
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Java
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
หากต้องการกู้คืนสถานะใน onCreate(Bundle)
ให้เรียกข้อมูลค่าที่เก็บไว้จากแพ็กเกจ โดยทำดังนี้
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
ดังที่กล่าวไว้ในตารางที่ 1 โปรดทราบว่าระบบจะเก็บตัวแปรไว้เมื่อวางข้อมูลโค้ดในกองซ้อนด้านหลัง การจัดการกับสถานะเหล่านี้เป็นสถานะที่บันทึกไว้จะช่วยให้สถานะดังกล่าวคงอยู่ตลอดการดำเนินการที่ทำลายข้อมูลทั้งหมด
ไม่มีการกำหนดค่า
ข้อมูล NonConfig ควรอยู่นอกส่วนของข้อมูล เช่น ใน ViewModel
ในตัวอย่างก่อนหน้าด้านบน seed
(สถานะ NonConfig ของเรา) จะสร้างขึ้นใน ViewModel
ViewModel
เป็นเจ้าของตรรกะในการรักษาสถานะ
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Java
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
คลาส ViewModel
จะช่วยให้ข้อมูลคงอยู่จากการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหน้าจอ และจะยังอยู่ในหน่วยความจำเมื่อวางส่วนย่อยในแบ็กสแต็ก หลังจากกระบวนการสิ้นสุดและสร้างใหม่ ระบบจะสร้าง ViewModel
ขึ้นมาใหม่และสร้าง seed
ใหม่ การเพิ่มข้อบังคับ SavedState
ลงใน ViewModel
จะช่วยให้ ViewModel
คงสถานะแบบง่ายไว้ได้แม้จะมีการหยุดทำงานและสร้างใหม่
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดการสถานะส่วนย่อยได้ที่ทรัพยากรเพิ่มเติมต่อไปนี้