ทั้งนี้ ขึ้นอยู่กับว่าคุณยึดสถานะใดเป็นหลักและตรรกะที่จำเป็น สามารถใช้ API ต่างๆ เพื่อจัดเก็บและคืนค่าสถานะ UI ของคุณ ทุกแอปใช้ API ต่างๆ ร่วมกันเพื่อให้บรรลุเป้าหมายนี้ได้ดีที่สุด
แอป Android อาจสูญเสียสถานะ UI เนื่องจากกิจกรรมหรือกระบวนการ นันทนาการ การสูญเสียสถานะนี้อาจเกิดขึ้นเนื่องจากเหตุการณ์ต่อไปนี้
- การเปลี่ยนแปลงการกำหนดค่า ระบบจะทำลายกิจกรรมและสร้างขึ้นใหม่ เว้นแต่ การเปลี่ยนแปลงการกำหนดค่าต้องจัดการด้วยตนเอง
- การสิ้นสุดกระบวนการที่เริ่มต้นโดยระบบ แอปทำงานอยู่ในเบื้องหลังและ อุปกรณ์ช่วยเพิ่มทรัพยากร (เช่น หน่วยความจำ) ไปให้กระบวนการอื่นๆ นำไปใช้
การรักษาสถานะหลังเหตุการณ์เหล่านี้มีความสําคัญอย่างยิ่งสําหรับผู้ใช้เชิงบวก ประสบการณ์การใช้งาน การเลือกสถานะที่จะคงไว้จะขึ้นอยู่กับผู้ใช้ที่ไม่ซ้ำของแอป ขั้นตอน แนวทางปฏิบัติที่ดีที่สุดคือ อย่างน้อยคุณควรเก็บข้อมูลจากผู้ใช้ และ สถานะที่เกี่ยวข้องกับการนำทาง ตัวอย่างเช่น ตำแหน่งการเลื่อนของ รายการ ซึ่งเป็นรหัสของรายการที่ผู้ใช้ต้องการรายละเอียดเพิ่มเติม อยู่ระหว่างดำเนินการ การเลือกค่ากำหนดของผู้ใช้ หรือการป้อนข้อมูลในช่องข้อความ
หน้านี้จะสรุป API ที่พร้อมใช้งานสำหรับจัดเก็บสถานะ UI โดยขึ้นอยู่กับตำแหน่ง สถานะของคุณก็จะสอดคล้องไป และตรรกะที่จำเป็นต้องใช้มัน
ตรรกะ UI
หากสถานะของคุณทอยอยู่ใน UI ไม่ว่าจะเป็นในฟังก์ชันที่ประกอบกันได้หรือแบบธรรมดา
คลาสผู้ถือสถานะที่กำหนดขอบเขตเฉพาะการเรียบเรียงคุณสามารถใช้
rememberSaveable
เพื่อรักษาสถานะของกิจกรรมและประมวลผลสันทนาการ
ในข้อมูลโค้ดต่อไปนี้ ใช้ rememberSaveable
เพื่อจัดเก็บบูลีนเดียว
สถานะองค์ประกอบ UI:
@Composable fun ChatBubble( message: Message ) { var showDetails by rememberSaveable { mutableStateOf(false) } ClickableText( text = AnnotatedString(message.content), onClick = { showDetails = !showDetails } ) if (showDetails) { Text(message.timestamp) } }
showDetails
เป็นตัวแปรบูลีนที่จัดเก็บไว้หากลูกโป่งแชทยุบอยู่
หรือขยายอยู่
rememberSaveable
จัดเก็บสถานะองค์ประกอบ UI ใน Bundle
ผ่าน
กลไกสถานะอินสแตนซ์ที่บันทึกไว้
โมเดลนี้สามารถจัดเก็บประเภทพื้นฐานไว้ในแพ็กเกจโดยอัตโนมัติ หากรัฐ
อยู่ในประเภทที่ไม่ใช่แบบพื้นฐาน เช่น คลาสข้อมูล
กลไกการจัดเก็บแบบต่างๆ เช่น การใช้คำอธิบายประกอบ Parcelize
โดยใช้ Compose API เช่น listSaver
และ mapSaver
หรือใช้
คลาสโปรแกรมประหยัดแบบกำหนดเองที่ขยายรันไทม์ของ Compose Saver
ดูเส้นทาง
ในการจัดเก็บเอกสารสถานะเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการเหล่านี้
ในข้อมูลโค้ดต่อไปนี้ การเขียนใน rememberLazyListState
API จัดเก็บ LazyListState
ซึ่งประกอบด้วยสถานะการเลื่อนของ
LazyColumn
หรือ LazyRow
โดยใช้ rememberSaveable
โดยใช้
LazyListState.Saver
ซึ่งเป็นโหมดประหยัดที่กำหนดเองที่
จัดเก็บและคืนค่าสถานะการเลื่อน หลังจากกิจกรรมหรือดำเนินการสันทนาการ (สำหรับ
ตัวอย่างเช่น หลังจากการกำหนดค่าเปลี่ยนไป เช่น เปลี่ยนการวางแนวของอุปกรณ์)
สถานะการเลื่อนจะยังคงอยู่
@Composable fun rememberLazyListState( initialFirstVisibleItemIndex: Int = 0, initialFirstVisibleItemScrollOffset: Int = 0 ): LazyListState { return rememberSaveable(saver = LazyListState.Saver) { LazyListState( initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset ) } }
แนวทางปฏิบัติแนะนำ
rememberSaveable
ใช้ Bundle
เพื่อจัดเก็บสถานะ UI ซึ่งแชร์โดย
API อื่นๆ ที่เขียนด้วย เช่น onSaveInstanceState()
ในการเรียก
กิจกรรมของคุณ อย่างไรก็ตาม ขนาดของ Bundle
นี้จำกัดและจัดเก็บขนาดใหญ่
อาจทำให้เกิดข้อยกเว้น TransactionTooLarge
ในรันไทม์ ช่วงเวลานี้
อาจจะเป็นปัญหาอย่างมากในแอป Activity
เดี่ยวที่
มีการใช้ Bundle
ในแอป
ในการหลีกเลี่ยงการขัดข้องประเภทนี้ คุณไม่ควรเก็บวัตถุที่ซับซ้อนขนาดใหญ่ หรือ รายการออบเจ็กต์ในกลุ่ม
ให้จัดเก็บสถานะขั้นต่ำที่จำเป็นแทน เช่น รหัสหรือคีย์ และใช้ตัวเลือกเหล่านี้เพื่อ มอบสิทธิ์การคืนค่าสถานะ UI ที่ซับซ้อนขึ้นให้กับกลไกอื่นๆ เช่น ถาวร พื้นที่เก็บข้อมูล
ตัวเลือกการออกแบบเหล่านี้จะขึ้นอยู่กับ Use Case เฉพาะของแอปและลักษณะ ผู้ใช้คาดหวังให้อุปกรณ์ทำงาน
ยืนยันการกู้คืนสถานะ
คุณสามารถยืนยันว่ารัฐที่จัดเก็บไว้กับ rememberSaveable
ใน
องค์ประกอบการเขียนจะได้รับการคืนค่าอย่างถูกต้องเมื่อกิจกรรมหรือกระบวนการ
สร้างใหม่ มี API เฉพาะที่ช่วยให้บรรลุเป้าหมายนี้ได้ เช่น
StateRestorationTester
ดูเอกสารการทดสอบเพื่อ
ดูข้อมูลเพิ่มเติม
ตรรกะทางธุรกิจ
หากสถานะองค์ประกอบ UI ของคุณถูกรอกไปที่ ViewModel
เนื่องจาก
คุณสามารถใช้ API ของ ViewModel
ได้ตามที่ตรรกะทางธุรกิจกำหนด
ประโยชน์หลักอย่างหนึ่งของการใช้ ViewModel
ในแอปพลิเคชัน Android คือ
ที่จัดการการเปลี่ยนแปลงการกำหนดค่าโดยไม่เสียค่าใช้จ่าย เมื่อมีการกำหนดค่า
เปลี่ยนแปลง และกิจกรรมจะถูกทำลายและสร้างขึ้นใหม่ สถานะ UI จะกลับสู่
ViewModel
จะเก็บไว้ในความทรงจำ หลังจากทำกิจกรรมสันทนาการ ViewModel
เดิม
แนบอยู่กับอินสแตนซ์กิจกรรมใหม่
แต่อินสแตนซ์ ViewModel
ยังคงอยู่หลังจากที่กระบวนการที่เริ่มต้นโดยระบบไปแล้ว
หากต้องการให้สถานะ UI พ้นจากการเปลี่ยนแปลงนี้ ให้ใช้โมดูลสถานะที่บันทึกไว้สำหรับ
ViewModel ซึ่งมี API SavedStateHandle
แนวทางปฏิบัติแนะนำ
SavedStateHandle
ยังใช้กลไก Bundle
ในการจัดเก็บสถานะ UI ดังนั้น
คุณควรใช้เพื่อจัดเก็บสถานะองค์ประกอบ UI แบบง่ายเท่านั้น
สถานะ UI ของหน้าจอ ซึ่งเกิดขึ้นจากการใช้กฎทางธุรกิจและการเข้าถึง
อื่นๆ ของแอปพลิเคชันของคุณนอกเหนือจาก UI ไม่ควรเก็บใน
SavedStateHandle
เนื่องจากอาจมีความซับซ้อนและขนาด คุณสามารถใช้
กลไกต่างๆ ในการจัดเก็บข้อมูลที่ซับซ้อนหรือขนาดใหญ่ เช่น ทรัพยากรถาวรในเครื่อง
พื้นที่เก็บข้อมูล หลังจากสร้างกระบวนการใหม่ หน้าจอจะสร้างขึ้นใหม่ด้วย
คืนค่าสถานะชั่วคราวที่เก็บไว้ใน SavedStateHandle
(หากมี) และ
สร้างสถานะ UI ของหน้าจออีกครั้งจากชั้นข้อมูล
SavedStateHandle
API
SavedStateHandle
มี API ที่แตกต่างกันสำหรับจัดเก็บสถานะองค์ประกอบ UI โดยส่วนใหญ่
สิ่งที่ควรทราบ:
เขียน State |
saveable() |
---|---|
StateFlow |
getStateFlow() |
เขียน State
ใช้ saveable
API ของ SavedStateHandle
เพื่ออ่านและเขียนองค์ประกอบ UI
ระบุเป็น MutableState
เพื่อให้รอดพ้นจากกิจกรรม และประมวลผลสันทนาการ
การตั้งค่าโค้ดขั้นต่ำ
saveable
API รองรับประเภทพื้นฐานที่พร้อมใช้งานทันทีและรับ
stateSaver
เพื่อใช้โปรแกรมประหยัดที่กำหนดเอง เช่นเดียวกับ rememberSaveable()
ในข้อมูลโค้ดต่อไปนี้ message
จะจัดเก็บประเภทอินพุตของผู้ใช้ใน
TextField
:
class ConversationViewModel( savedStateHandle: SavedStateHandle ) : ViewModel() { var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue("")) } private set fun update(newMessage: TextFieldValue) { message = newMessage } /*...*/ } val viewModel = ConversationViewModel(SavedStateHandle()) @Composable fun UserInput(/*...*/) { TextField( value = viewModel.message, onValueChange = { viewModel.update(it) } ) }
ดูเอกสารประกอบของ SavedStateHandle
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ
โดยใช้ saveable
API
StateFlow
ใช้ getStateFlow()
เพื่อจัดเก็บสถานะองค์ประกอบ UI และใช้เป็นขั้นตอน
จาก SavedStateHandle
อ่าน StateFlow
แล้ว
และ API กำหนดให้คุณต้องระบุคีย์เพื่อแทนที่โฟลว์ได้
ปล่อยค่าใหม่ เมื่อใช้คีย์ที่กำหนดค่าไว้ คุณสามารถเรียกข้อมูล StateFlow
และรวบรวมค่าล่าสุด
ในข้อมูลโค้ด savedFilterType
เป็นตัวแปร StateFlow
ที่
จัดเก็บประเภทตัวกรองที่ใช้กับรายการช่องแชทในแอปแชท ได้แก่
private const val CHANNEL_FILTER_SAVED_STATE_KEY = "ChannelFilterKey" class ChannelViewModel( channelsRepository: ChannelsRepository, private val savedStateHandle: SavedStateHandle ) : ViewModel() { private val savedFilterType: StateFlow<ChannelsFilterType> = savedStateHandle.getStateFlow( key = CHANNEL_FILTER_SAVED_STATE_KEY, initialValue = ChannelsFilterType.ALL_CHANNELS ) private val filteredChannels: Flow<List<Channel>> = combine(channelsRepository.getAll(), savedFilterType) { channels, type -> filter(channels, type) }.onStart { emit(emptyList()) } fun setFiltering(requestType: ChannelsFilterType) { savedStateHandle[CHANNEL_FILTER_SAVED_STATE_KEY] = requestType } /*...*/ } enum class ChannelsFilterType { ALL_CHANNELS, RECENT_CHANNELS, ARCHIVED_CHANNELS }
ทุกครั้งที่ผู้ใช้เลือกประเภทตัวกรองใหม่ ระบบจะเรียกใช้ setFiltering
ช่วงเวลานี้
บันทึกค่าใหม่ใน SavedStateHandle
ซึ่งจัดเก็บไว้กับคีย์
_CHANNEL_FILTER_SAVED_STATE_KEY_
savedFilterType
คือโฟลว์ที่มีการปล่อย
ค่าล่าสุดที่จัดเก็บในคีย์ filteredChannels
ได้สมัครรับขั้นตอน
ดำเนินการกรองช่อง
โปรดดูSavedStateHandle
เอกสารประกอบสำหรับข้อมูลเพิ่มเติมเกี่ยวกับ
getStateFlow()
API
สรุป
ตารางต่อไปนี้สรุป API ที่ครอบคลุมในส่วนนี้ และกรณีที่ควรใช้ เพื่อบันทึกสถานะ UI แต่ละรายการ
กิจกรรม | ตรรกะ UI | ตรรกะทางธุรกิจใน ViewModel |
---|---|---|
การเปลี่ยนแปลงการกำหนดค่า | rememberSaveable |
อัตโนมัติ |
การสิ้นสุดกระบวนการที่เริ่มต้นโดยระบบ | rememberSaveable |
SavedStateHandle |
API ที่จะใช้จะขึ้นอยู่กับตำแหน่งของสถานะและตรรกะที่สถานะดังกล่าว
ต้องการ สำหรับสถานะที่ใช้ในตรรกะ UI ให้ใช้ rememberSaveable
สำหรับ
ที่ใช้ในตรรกะทางธุรกิจหากคุณมีอยู่ในViewModel
บันทึกโดยใช้ SavedStateHandle
คุณควรใช้ API ของ Bundle (rememberSaveable
และ SavedStateHandle
) เพื่อ
จัดเก็บสถานะ UI ขนาดเล็ก ข้อมูลนี้เป็นข้อมูลต่ำสุดที่จำเป็นในการกู้คืน
UI จะกลับสู่สถานะก่อนหน้า พร้อมกับกลไกการจัดเก็บอื่นๆ สำหรับ
เช่น หากคุณจัดเก็บรหัสของโปรไฟล์ที่ผู้ใช้ดูไว้ในแพ็กเกจ
คุณสามารถดึงข้อมูลขนาดใหญ่ เช่น รายละเอียดโปรไฟล์ จากชั้นข้อมูลได้
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการต่างๆ ในการบันทึกสถานะ UI โปรดดู การบันทึกเอกสารสถานะ UI และหน้าชั้นข้อมูลของ สถาปัตยกรรม
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- วิธียกสถานะ
- State และ Jetpack Compose
- รายการและตารางกริด