แนวคิดและการติดตั้งใช้งาน Jetpack Compose
คำแนะนำนี้จะกล่าวถึงความคาดหวังของผู้ใช้เกี่ยวกับสถานะ UI และตัวเลือกต่างๆ ที่มีสำหรับการเก็บรักษาสถานะ
การบันทึกและกู้คืนสถานะ UI ของกิจกรรมอย่างรวดเร็วหลังจากที่ระบบทำลายกิจกรรมหรือแอปพลิเคชันเป็นสิ่งสำคัญเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี ผู้ใช้คาดหวังว่าสถานะ UI จะยังคงเหมือนเดิม แต่ระบบอาจทำลายกิจกรรมและสถานะที่จัดเก็บไว้
หากต้องการลดช่องว่างระหว่างความคาดหวังของผู้ใช้กับลักษณะการทำงานของระบบ ให้ใช้วิธีการต่อไปนี้ร่วมกัน
ViewModelออบเจ็กต์- สถานะอินสแตนซ์ที่บันทึกไว้ในบริบทต่อไปนี้
- View:
onSaveInstanceState()API - ViewModel:
SavedStateHandle.
- View:
- พื้นที่เก็บข้อมูลในเครื่องเพื่อเก็บรักษาสถานะ UI ไว้ระหว่างการเปลี่ยนแอปและกิจกรรม
โซลูชันที่เหมาะสมที่สุดจะขึ้นอยู่กับความซับซ้อนของข้อมูล UI, Use Case ของแอป และการสร้างสมดุลระหว่างความเร็วในการเข้าถึงข้อมูลกับการใช้หน่วยความจำ
ตรวจสอบว่าแอปของคุณตรงตามความคาดหวังของผู้ใช้และมีอินเทอร์เฟซที่รวดเร็วและตอบสนองได้ดี หลีกเลี่ยงความล่าช้าเมื่อโหลดข้อมูลลงใน UI โดยเฉพาะอย่างยิ่งหลังจากการเปลี่ยนแปลงการกำหนดค่าทั่วไป เช่น การหมุน
ความคาดหวังของผู้ใช้และลักษณะการทำงานของระบบ
ผู้ใช้คาดหวังว่าสถานะกิจกรรมจะถูกล้างหรือเก็บรักษาไว้ ทั้งนี้ขึ้นอยู่กับการดำเนินการที่ผู้ใช้ทำ ในบางกรณี ระบบจะดำเนินการตามที่ผู้ใช้คาดหวังโดยอัตโนมัติ แต่ในบางกรณีระบบจะดำเนินการตรงกันข้าม
การยกเลิกสถานะ UI ที่ผู้ใช้เป็นผู้เริ่ม
ผู้ใช้คาดหวังว่าเมื่อเริ่มกิจกรรม สถานะ UI ชั่วคราวของกิจกรรมนั้นจะยังคงเหมือนเดิมจนกว่าผู้ใช้จะยกเลิกกิจกรรมโดยสมบูรณ์ ผู้ใช้สามารถยกเลิกกิจกรรมโดยสมบูรณ์ได้โดยทำดังนี้
- ปัดกิจกรรมออกจากหน้าจอภาพรวม (แอปที่ใช้ล่าสุด)
- บังคับหยุดหรือปิดแอปจากหน้าจอการตั้งค่า
- รีบูตอุปกรณ์
- ดำเนินการ "สิ้นสุด" บางอย่าง (ซึ่งได้รับการสนับสนุนโดย
Activity.finish())
ในกรณีที่ยกเลิกโดยสมบูรณ์เหล่านี้ ผู้ใช้จะสันนิษฐานว่าตนได้ออกจากกิจกรรมนั้นอย่างถาวรแล้ว และหากเปิดกิจกรรมอีกครั้ง ผู้ใช้คาดหวังว่ากิจกรรมจะเริ่มต้นจากสถานะที่สะอาด ลักษณะการทำงานของระบบเบื้องหลังสำหรับสถานการณ์การยกเลิกเหล่านี้ตรงกับความคาดหวังของผู้ใช้ นั่นคือ อินสแตนซ์กิจกรรมจะถูกทำลายและนำออกจากหน่วยความจำ พร้อมกับสถานะที่จัดเก็บไว้ในอินสแตนซ์และบันทึกสถานะอินสแตนซ์ที่บันทึกไว้ซึ่งเชื่อมโยงกับกิจกรรม
อย่างไรก็ตาม มีข้อยกเว้นบางประการสำหรับกฎเกี่ยวกับการยกเลิกโดยสมบูรณ์นี้ เช่น ผู้ใช้อาจคาดหวังให้เบราว์เซอร์นำผู้ใช้ไปยังหน้าเว็บที่ผู้ใช้ดูอยู่ก่อนที่จะออกจากเบราว์เซอร์โดยใช้ปุ่มย้อนกลับ
การยกเลิกสถานะ UI ที่ระบบเป็นผู้เริ่ม
ผู้ใช้คาดหวังว่าสถานะ UI ของกิจกรรมจะยังคงเหมือนเดิมตลอดการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหรือการเปลี่ยนเป็นโหมดหลายหน้าต่าง อย่างไรก็ตาม โดยค่าเริ่มต้น ระบบจะทำลายกิจกรรมเมื่อมีการเปลี่ยนแปลงการกำหนดค่าดังกล่าว ซึ่งจะล้างสถานะ UI ที่จัดเก็บไว้ในอินสแตนซ์กิจกรรม ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าอุปกรณ์ได้ที่ หน้าอ้างอิงการกำหนดค่า
โปรดทราบว่าคุณสามารถลบล้างลักษณะการทำงานเริ่มต้นสำหรับการเปลี่ยนแปลงการกำหนดค่าได้ (แม้ว่าจะไม่แนะนำ) ดูรายละเอียดเพิ่มเติมได้ที่ การจัดการการ เปลี่ยนแปลงการกำหนดค่า
นอกจากนี้ ผู้ใช้ยังคาดหวังว่าสถานะ UI ของกิจกรรมจะยังคงเหมือนเดิมหากผู้ใช้เปลี่ยนไปใช้แอปอื่นชั่วคราวแล้วกลับมาใช้แอปของคุณในภายหลัง ตัวอย่างเช่น ผู้ใช้ทำการค้นหาในกิจกรรมการค้นหาของคุณ แล้วกดปุ่มหน้าแรกหรือรับสายโทรศัพท์ เมื่อกลับมาที่กิจกรรมการค้นหา ผู้ใช้คาดหวังว่าจะเห็นคีย์เวิร์ดและผลการค้นหายังคงอยู่เหมือนเดิมทุกประการ
ในสถานการณ์นี้ ระบบจะวางแอปของคุณไว้ในเบื้องหลัง และระบบจะพยายามอย่างเต็มที่เพื่อเก็บกระบวนการของแอปไว้ในหน่วยความจำ อย่างไรก็ตาม ระบบอาจทำลายกระบวนการของแอปพลิเคชันในขณะที่ผู้ใช้ไม่อยู่และโต้ตอบกับแอปอื่นๆ ในกรณีดังกล่าว อินสแตนซ์กิจกรรมจะถูกทำลาย พร้อมกับสถานะที่จัดเก็บไว้ในอินสแตนซ์ เมื่อผู้ใช้เปิดแอปอีกครั้ง กิจกรรมจะอยู่ในสถานะที่สะอาดอย่างไม่คาดคิด ดูข้อมูลเพิ่มเติมเกี่ยวกับการสิ้นสุดกระบวนการได้ที่ กระบวนการและวงจรการทำงานของแอป
ตัวเลือกในการเก็บรักษาสถานะ UI
เมื่อความคาดหวังของผู้ใช้เกี่ยวกับสถานะ UI ไม่ตรงกับลักษณะการทำงานเริ่มต้นของระบบ คุณต้องบันทึกและกู้คืนสถานะ UI ของผู้ใช้เพื่อให้การทำลายที่ระบบเป็นผู้เริ่มนั้นโปร่งใสต่อผู้ใช้
ตัวเลือกแต่ละรายการสำหรับการเก็บรักษาสถานะ UI จะแตกต่างกันไปตามมิติข้อมูลต่อไปนี้ซึ่งส่งผลต่อประสบการณ์การใช้งานของผู้ใช้
ViewModel |
สถานะอินสแตนซ์ที่บันทึกไว้ |
พื้นที่เก็บข้อมูลถาวร |
|
ตำแหน่งของพื้นที่เก็บข้อมูล |
ในหน่วยความจำ |
ในหน่วยความจำ |
ในดิสก์หรือเครือข่าย |
ยังคงอยู่หลังจากการเปลี่ยนแปลงการกำหนดค่า |
ได้ |
ได้ |
ได้ |
ยังคงอยู่หลังจากการสิ้นสุดกระบวนการที่ระบบเป็นผู้เริ่ม |
ไม่ได้ |
ใช่ |
ได้ |
ยังคงอยู่หลังจากการยกเลิก/สิ้นสุดกิจกรรมโดยสมบูรณ์ของผู้ใช้ |
ไม่ได้ |
ไม่ได้ |
ได้ |
ข้อจำกัดของข้อมูล |
ออบเจ็กต์ที่ซับซ้อนใช้ได้ แต่พื้นที่ถูกจำกัดตามหน่วยความจำที่พร้อมใช้งาน |
ใช้ได้เฉพาะกับประเภทข้อมูลพื้นฐานและออบเจ็กต์ขนาดเล็กที่เรียบง่าย เช่น |
ถูกจำกัดโดยพื้นที่ดิสก์หรือค่าใช้จ่าย / เวลาในการดึงข้อมูลจากแหล่งข้อมูลเครือข่ายเท่านั้น |
เวลาอ่าน/เขียน |
รวดเร็ว (เข้าถึงหน่วยความจำเท่านั้น) |
ช้า (ต้องมีการซีเรียลไลซ์/ดีซีเรียลไลซ์) |
ช้า (ต้องเข้าถึงดิสก์หรือทำธุรกรรมเครือข่าย) |
ใช้ ViewModel เพื่อจัดการการเปลี่ยนแปลงการกำหนดค่า
ViewModel เหมาะอย่างยิ่งสำหรับการจัดเก็บและจัดการข้อมูลที่เกี่ยวข้องกับ UI ขณะที่ผู้ใช้ใช้งานแอปพลิเคชันอยู่ ซึ่งช่วยให้เข้าถึงข้อมูล UI ได้อย่างรวดเร็วและช่วยให้คุณไม่ต้องดึงข้อมูลจากเครือข่ายหรือดิสก์อีกครั้งเมื่อมีการหมุน การปรับขนาดหน้าต่าง และการเปลี่ยนแปลงการกำหนดค่าอื่นๆ ที่เกิดขึ้นบ่อยๆ ดูวิธีติดตั้งใช้งาน ViewModel ได้ที่คู่มือ ViewModel
ViewModel จะเก็บข้อมูลไว้ในหน่วยความจำ ซึ่งหมายความว่าการดึงข้อมูลจะใช้ค่าใช้จ่ายน้อยกว่าการดึงข้อมูลจากดิสก์หรือเครือข่าย ViewModel จะเชื่อมโยงกับกิจกรรม (หรือเจ้าของวงจรการทำงานอื่นๆ) โดยจะอยู่ในหน่วยความจำระหว่างการเปลี่ยนแปลงการกำหนดค่า และระบบจะเชื่อมโยง ViewModel กับอินสแตนซ์กิจกรรมใหม่ที่เกิดจากการเปลี่ยนแปลงการกำหนดค่าโดยอัตโนมัติ
ระบบจะทำลาย ViewModel โดยอัตโนมัติเมื่อผู้ใช้กลับออกจากกิจกรรมหรือ Fragment หรือหากคุณเรียกใช้ finish() ซึ่งหมายความว่าสถานะจะถูกล้างตามที่ผู้ใช้คาดหวังในสถานการณ์เหล่านี้
ViewModel จะถูกทำลายระหว่างการสิ้นสุดการประมวลผลที่ระบบเป็นผู้เริ่ม ซึ่งแตกต่างจากสถานะอินสแตนซ์ที่บันทึกไว้ หากต้องการโหลดข้อมูลอีกครั้งหลังจากที่ระบบเป็นผู้เริ่มกระบวนการสิ้นสุดใน
ViewModel ให้ใช้ SavedStateHandle API หรือหากข้อมูลเกี่ยวข้องกับ UI และไม่จำเป็นต้องเก็บไว้ใน ViewModel ให้ใช้ onSaveInstanceState() แต่หากข้อมูลเป็น ข้อมูลแอปพลิเคชัน การเก็บข้อมูลไว้ในดิสก์อาจเป็นวิธีที่
ดีกว่า
หากคุณมีโซลูชันในหน่วยความจำสำหรับการจัดเก็บสถานะ UI ไว้แล้วเมื่อมีการเปลี่ยนแปลงการกำหนดค่า คุณอาจไม่จำเป็นต้องใช้ ViewModel
ใช้สถานะอินสแตนซ์ที่บันทึกไว้เป็นข้อมูลสำรองเพื่อจัดการการสิ้นสุดการประมวลผลที่ระบบเป็นผู้เริ่ม
การเรียกกลับ onSaveInstanceState() ในระบบ View และ
SavedStateHandle ใน ViewModel จะจัดเก็บข้อมูลที่จำเป็นในการโหลดสถานะของ
ตัวควบคุม UI อีกครั้ง เช่น กิจกรรมหรือ Fragment หากระบบทำลายและ
สร้างตัวควบคุมนั้นขึ้นมาใหม่ในภายหลัง ดูวิธีติดตั้งใช้งานสถานะอินสแตนซ์ที่บันทึกไว้
โดยใช้ onSaveInstanceState ได้ที่ การบันทึกและกู้คืนสถานะกิจกรรม ใน
คู่มือวงจรการทำงานของกิจกรรม
บันเดิลสถานะอินสแตนซ์ที่บันทึกไว้จะยังคงอยู่เมื่อมีการเปลี่ยนแปลงการกำหนดค่าและการสิ้นสุดการประมวลผล แต่ถูกจำกัดโดยพื้นที่เก็บข้อมูลและความเร็ว เนื่องจาก API ต่างๆ จะซีเรียลไลซ์ข้อมูล การซีเรียลไลซ์อาจใช้หน่วยความจำจำนวนมากหากออบเจ็กต์ที่กำลังซีเรียลไลซ์มีความซับซ้อน เนื่องจากกระบวนการนี้เกิดขึ้นในเทรดหลักระหว่างการเปลี่ยนแปลงการกำหนดค่า การเรียงอันดับที่ใช้เวลานานอาจทำให้เฟรมหลุดและการกระตุกแบบข้ามเฟรม
อย่าใช้สถานะอินสแตนซ์ที่บันทึกไว้เพื่อจัดเก็บข้อมูลจำนวนมาก เช่น บิตแมป รวมถึงโครงสร้างข้อมูลที่ซับซ้อนซึ่งต้องใช้การซีเรียลไลซ์หรือดีซีเรียลไลซ์เป็นเวลานาน แต่ให้จัดเก็บเฉพาะประเภทข้อมูลพื้นฐานและออบเจ็กต์ขนาดเล็กที่เรียบง่าย เช่น String ดังนั้น ให้ใช้สถานะอินสแตนซ์ที่บันทึกไว้เพื่อจัดเก็บข้อมูลจำนวนน้อยที่สุดที่จำเป็น เช่น รหัส เพื่อสร้างข้อมูลที่จำเป็นในการกู้คืน UI กลับสู่สถานะก่อนหน้าหากกลไกการเก็บข้อมูลอื่นๆ ล้มเหลว แอปส่วนใหญ่ควรติดตั้งใช้งานกลไกนี้เพื่อจัดการการสิ้นสุดการประมวลผลที่ระบบเป็นผู้เริ่ม
คุณอาจไม่จำเป็นต้องใช้สถานะอินสแตนซ์ที่บันทึกไว้เลย ทั้งนี้ขึ้นอยู่กับกรณีการใช้งานของแอป ตัวอย่างเช่น เบราว์เซอร์อาจนำผู้ใช้กลับไปยังหน้าเว็บที่ผู้ใช้ดูอยู่ก่อนที่จะออกจากเบราว์เซอร์ หากกิจกรรมของคุณมีลักษณะการทำงานเช่นนี้ คุณสามารถละเว้นการใช้สถานะอินสแตนซ์ที่บันทึกไว้และเก็บข้อมูลทุกอย่างไว้ในเครื่องแทน
นอกจากนี้ เมื่อคุณเปิดกิจกรรมจาก Intent ระบบจะส่งบันเดิลส่วนเพิ่มเติมไปยังกิจกรรมทั้งเมื่อมีการเปลี่ยนแปลงการกำหนดค่าและเมื่อระบบกู้คืนกิจกรรม
ในสถานการณ์ใดสถานการณ์หนึ่งต่อไปนี้ คุณควรใช้ ViewModel เพื่อหลีกเลี่ยง
การเสียรอบการทำงานในการโหลดข้อมูลจากฐานข้อมูลอีกครั้งระหว่างการเปลี่ยนแปลงการกำหนดค่า
ในกรณีที่ข้อมูล UI ที่จะเก็บรักษามีความเรียบง่ายและมีขนาดเล็ก คุณอาจใช้เฉพาะ API สถานะอินสแตนซ์ที่บันทึกไว้เพื่อเก็บรักษาข้อมูลสถานะ
เชื่อมต่อกับสถานะที่บันทึกไว้โดยใช้ SavedStateRegistry
ตั้งแต่ Fragment 1.1.0 หรือ Activity
1.0.0 ซึ่งเป็นทรัพยากร Dependency แบบถ่ายทอด ตัวควบคุม UI เช่น Activity หรือ Fragment จะติดตั้งใช้งาน
SavedStateRegistryOwner และมี SavedStateRegistry ที่
เชื่อมโยงกับตัวควบคุมนั้น SavedStateRegistry ช่วยให้คอมโพเนนต์เชื่อมต่อกับสถานะที่บันทึกไว้ของตัวควบคุม UI เพื่อใช้หรือมีส่วนร่วมในสถานะดังกล่าว ตัวอย่างเช่น
โมดูลสถานะที่บันทึกไว้สำหรับ ViewModel ใช้ SavedStateRegistry เพื่อสร้าง
SavedStateHandle และมอบให้กับออบเจ็กต์ ViewModel คุณสามารถดึงข้อมูล
SavedStateRegistry จากภายในตัวควบคุม UI ได้โดยเรียกใช้
getSavedStateRegistry
คอมโพเนนต์ที่มีส่วนร่วมในสถานะที่บันทึกไว้ต้องติดตั้งใช้งาน
SavedStateRegistry.SavedStateProvider ซึ่งกำหนดเมธอดเดียว
ที่เรียกว่า saveState เมธอด saveState() ช่วยให้คอมโพเนนต์แสดงผล Bundle ที่มีสถานะที่ควรบันทึกจากคอมโพเนนต์นั้น
SavedStateRegistry จะเรียกใช้เมธอดนี้ในระหว่างระยะการบันทึกสถานะของวงจรการทำงานของตัวควบคุม UI
class SearchManager implements SavedStateRegistry.SavedStateProvider {
private static String QUERY = "query";
private String query = null;
...
@NonNull
@Override
public Bundle saveState() {
Bundle bundle = new Bundle();
bundle.putString(QUERY, query);
return bundle;
}
}
หากต้องการลงทะเบียน SavedStateProvider ให้เรียกใช้ registerSavedStateProvider() ใน SavedStateRegistry โดยส่งคีย์เพื่อเชื่อมโยงกับข้อมูลของผู้ให้บริการ รวมถึงผู้ให้บริการ คุณสามารถดึงข้อมูลที่บันทึกไว้ก่อนหน้านี้สำหรับผู้ให้บริการได้จากสถานะที่บันทึกไว้โดยเรียกใช้ consumeRestoredStateForKey()
ใน SavedStateRegistry โดยส่งคีย์ที่เชื่อมโยงกับข้อมูลของผู้ให้บริการ
ภายใน Activity หรือ Fragment คุณสามารถลงทะเบียน SavedStateProvider ใน
onCreate() หลังจากเรียกใช้ super.onCreate() หรือคุณจะตั้งค่า
LifecycleObserver ใน SavedStateRegistryOwner ซึ่งติดตั้งใช้งาน
LifecycleOwner และลงทะเบียน SavedStateProvider เมื่อเกิดเหตุการณ์
ON_CREATE การใช้ LifecycleObserver จะช่วยให้คุณแยกการลงทะเบียนและการดึงข้อมูลสถานะที่บันทึกไว้ก่อนหน้านี้ออกจาก SavedStateRegistryOwner เอง
Kotlin
class SearchManager(registryOwner: SavedStateRegistryOwner) : SavedStateRegistry.SavedStateProvider {
companion object {
private const val PROVIDER = "search_manager"
private const val QUERY = "query"
}
private val query: String? = null
init {
// Register a LifecycleObserver for when the Lifecycle hits ON_CREATE
registryOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_CREATE) {
val registry = registryOwner.savedStateRegistry
// Register this object for future calls to saveState()
registry.registerSavedStateProvider(PROVIDER, this)
// Get the previously saved state and restore it
val state = registry.consumeRestoredStateForKey(PROVIDER)
// Apply the previously saved state
query = state?.getString(QUERY)
}
}
}
override fun saveState(): Bundle {
return bundleOf(QUERY to query)
}
...
}
class SearchFragment : Fragment() {
private var searchManager = SearchManager(this)
...
}
Java
class SearchManager implements SavedStateRegistry.SavedStateProvider {
private static String PROVIDER = "search_manager";
private static String QUERY = "query";
private String query = null;
public SearchManager(SavedStateRegistryOwner registryOwner) {
registryOwner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
if (event == Lifecycle.Event.ON_CREATE) {
SavedStateRegistry registry = registryOwner.getSavedStateRegistry();
// Register this object for future calls to saveState()
registry.registerSavedStateProvider(PROVIDER, this);
// Get the previously saved state and restore it
Bundle state = registry.consumeRestoredStateForKey(PROVIDER);
// Apply the previously saved state
if (state != null) {
query = state.getString(QUERY);
}
}
});
}
@NonNull
@Override
public Bundle saveState() {
Bundle bundle = new Bundle();
bundle.putString(QUERY, query);
return bundle;
}
...
}
class SearchFragment extends Fragment {
private SearchManager searchManager = new SearchManager(this);
...
}
ใช้การเก็บข้อมูลถาวรในเครื่องเพื่อจัดการการสิ้นสุดการประมวลผลสำหรับข้อมูลที่ซับซ้อนหรือมีขนาดใหญ่
พื้นที่เก็บข้อมูลถาวรในเครื่อง เช่น ฐานข้อมูลหรือค่ากำหนดที่แชร์ จะยังคงอยู่ตราบใดที่แอปพลิเคชันของคุณยังคงติดตั้งอยู่ในอุปกรณ์ของผู้ใช้ (เว้นแต่ผู้ใช้จะล้างข้อมูลของแอป) แม้ว่าพื้นที่เก็บข้อมูลในเครื่องดังกล่าวจะยังคงอยู่หลังจากการสิ้นสุดการประมวลผลของกิจกรรมและแอปพลิเคชันที่ระบบเป็นผู้เริ่ม แต่การดึงข้อมูลอาจมีค่าใช้จ่ายสูงเนื่องจากต้องอ่านจากพื้นที่เก็บข้อมูลในเครื่องลงในหน่วยความจำ พื้นที่เก็บข้อมูลถาวรในเครื่องนี้อาจเป็นส่วนหนึ่งของสถาปัตยกรรมแอปพลิเคชันอยู่แล้วเพื่อจัดเก็บข้อมูลทั้งหมดที่คุณไม่ต้องการให้สูญหายหากคุณเปิดและปิดกิจกรรม
ทั้ง ViewModel และสถานะอินสแตนซ์ที่บันทึกไว้ไม่ใช่โซลูชันพื้นที่เก็บข้อมูลระยะยาว จึงไม่สามารถใช้แทนพื้นที่เก็บข้อมูลในเครื่อง เช่น ฐานข้อมูล แต่คุณควรใช้กลไกเหล่านี้เพื่อจัดเก็บสถานะ UI ชั่วคราวเท่านั้น และใช้พื้นที่เก็บข้อมูลถาวรสำหรับข้อมูลแอปอื่นๆ ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้ประโยชน์จากพื้นที่เก็บข้อมูลในเครื่องเพื่อเก็บข้อมูลโมเดลแอปไว้ในระยะยาว (เช่น เมื่อรีสตาร์ทอุปกรณ์) ได้ที่คู่มือสถาปัตยกรรมแอป
การจัดการสถานะ UI: แบ่งและเอาชนะ
คุณสามารถบันทึกและกู้คืนสถานะ UI ได้อย่างมีประสิทธิภาพโดยแบ่งงานระหว่างกลไกการเก็บข้อมูลถาวรประเภทต่างๆ ในกรณีส่วนใหญ่ กลไกแต่ละอย่างเหล่านี้ควรจัดเก็บข้อมูลประเภทต่างๆ ที่ใช้ในกิจกรรม โดยอิงตามข้อดีข้อเสียของความซับซ้อนของข้อมูล ความเร็วในการเข้าถึง และอายุการใช้งาน
- การเก็บข้อมูลถาวรในเครื่อง: จัดเก็บข้อมูลแอปพลิเคชันทั้งหมดที่คุณไม่ต้องการให้สูญหายหากคุณเปิดและปิดกิจกรรม
- ตัวอย่าง: คอลเล็กชันออบเจ็กต์เพลง ซึ่งอาจรวมถึงไฟล์เสียงและข้อมูลเมตา
ViewModel: จัดเก็บข้อมูลทั้งหมดที่จำเป็นในการแสดง UI ที่เชื่อมโยง ไว้ในหน่วยความจำ ซึ่งก็คือสถานะ UI ของหน้าจอ- ตัวอย่าง: ออบเจ็กต์เพลงของการค้นหาล่าสุดและข้อความค้นหาล่าสุด
- สถานะอินสแตนซ์ที่บันทึกไว้: จัดเก็บข้อมูลจำนวนเล็กน้อยที่จำเป็นในการโหลดสถานะ UI อีกครั้งหากระบบหยุดและสร้าง UI ขึ้นมาใหม่ แทนที่จะจัดเก็บออบเจ็กต์ที่ซับซ้อนไว้ที่นี่ ให้เก็บออบเจ็กต์ที่ซับซ้อนไว้ในพื้นที่เก็บข้อมูลในเครื่อง และจัดเก็บรหัสที่ไม่ซ้ำกันสำหรับออบเจ็กต์เหล่านี้ไว้ใน API สถานะอินสแตนซ์ที่บันทึกไว้
- ตัวอย่าง: การจัดเก็บข้อความค้นหาล่าสุด
ตัวอย่างเช่น ลองพิจารณากิจกรรมที่ช่วยให้คุณค้นหาในคลังเพลง วิธีจัดการเหตุการณ์ต่างๆ มีดังนี้
เมื่อผู้ใช้เพิ่มเพลง ViewModel จะมอบหมายให้เก็บข้อมูลนี้ไว้ในเครื่อง
ทันที หากควรแสดงเพลงที่เพิ่มใหม่นี้ใน UI คุณควรจะอัปเดตข้อมูลในออบเจ็กต์ ViewModel เพื่อแสดงการเพิ่มเพลงด้วย อย่าลืมทำการแทรกฐานข้อมูลทั้งหมดออกจากเทรดหลัก
เมื่อผู้ใช้ค้นหาเพลง ข้อมูลเพลงที่ซับซ้อนใดก็ตามที่คุณโหลดจากฐานข้อมูลควรจัดเก็บไว้ในออบเจ็กต์ ViewModel ทันที ซึ่งเป็นส่วนหนึ่งของสถานะ UI ของหน้าจอ
เมื่อกิจกรรมเข้าสู่เบื้องหลังและระบบเรียกใช้ API สถานะอินสแตนซ์ที่บันทึกไว้ ข้อความค้นหาควรจัดเก็บไว้ในสถานะอินสแตนซ์ที่บันทึกไว้ในกรณีที่กระบวนการสร้างขึ้นมาใหม่ เนื่องจากข้อมูลนี้จำเป็นในการโหลดข้อมูลแอปพลิเคชันที่เก็บไว้ใน API นี้ ให้จัดเก็บข้อความค้นหาไว้ใน SavedStateHandle ของ ViewModel ข้อมูลนี้เป็นข้อมูลทั้งหมดที่คุณต้องใช้ในการโหลดข้อมูลและทำให้ UI กลับสู่สถานะปัจจุบัน
กู้คืนสถานะที่ซับซ้อน: ประกอบชิ้นส่วนต่างๆ เข้าด้วยกัน
เมื่อผู้ใช้กลับมาที่กิจกรรม มี 2 สถานการณ์ที่เป็นไปได้สำหรับการสร้างกิจกรรมขึ้นมาใหม่
- ระบบสร้างกิจกรรมขึ้นมาใหม่หลังจากที่หยุดกิจกรรม ระบบจะบันทึกการค้นหาไว้ในบันเดิลสถานะอินสแตนซ์ที่บันทึกไว้ และ UI ควรส่งการค้นหาไปยัง
ViewModelหากไม่ได้ใช้SavedStateHandleViewModelจะเห็นว่าไม่มีผลการค้นหาที่แคชไว้และมอบหมายให้โหลดผลการค้นหาโดยใช้ข้อความค้นหาที่ระบุ - ระบบสร้างกิจกรรมขึ้นมาใหม่หลังจากการเปลี่ยนแปลงการกำหนดค่า เนื่องจากอินสแตนซ์
ViewModelไม่ได้ถูกทำลายViewModelจึงมีข้อมูลทั้งหมดที่แคชไว้ในหน่วยความจำและไม่จำเป็นต้องค้นหาฐานข้อมูลอีกครั้ง
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกสถานะ UI ได้จากแหล่งข้อมูลต่อไปนี้
บล็อก
- ViewModel: ตัวอย่างง่ายๆ
- ViewModel: การเก็บข้อมูลถาวร,
onSaveInstanceState, การกู้คืนสถานะ UI และตัวโหลด