สถานะในแอปคือค่าใดก็ได้ที่เปลี่ยนแปลงได้เมื่อเวลาผ่านไป คำจำกัดความนี้กว้างมากและครอบคลุมตั้งแต่ฐานข้อมูล Room ไปจนถึงตัวแปรในคลาส
แอป Android ทั้งหมดจะแสดงสถานะต่อผู้ใช้ ตัวอย่างสถานะใน Android App
- แซนบาร์ที่แสดงเมื่อเชื่อมต่อเครือข่ายไม่ได้
- บล็อกโพสต์และความคิดเห็นที่เกี่ยวข้อง
- ภาพเคลื่อนไหวแบบกระเพื่อมบนปุ่มที่เล่นเมื่อผู้ใช้คลิก
- สติกเกอร์ที่ผู้ใช้วาดทับรูปภาพได้
Jetpack Compose ช่วยให้คุณระบุตำแหน่งและวิธีจัดเก็บและใช้สถานะในแอป Android ได้อย่างชัดเจน คู่มือนี้มุ่งเน้นที่การเชื่อมต่อระหว่างสถานะกับคอมโพสิเบิล และ API ที่ Jetpack Compose มีให้ใช้งานเพื่อทำงานกับสถานะได้ง่ายขึ้น
สถานะและองค์ประกอบ
คอมโพสิชันเป็นแบบประกาศ ดังนั้นวิธีเดียวที่จะอัปเดตได้คือเรียกใช้คอมโพสิชันเดียวกันด้วยอาร์กิวเมนต์ใหม่ โดยอาร์กิวเมนต์เหล่านี้แสดงสถานะของ UI ทุกครั้งที่มีการอัปเดตสถานะ ระบบจะจัดองค์ประกอบใหม่ ด้วยเหตุนี้ องค์ประกอบอย่าง TextField
จึงจะไม่อัปเดตโดยอัตโนมัติเหมือนในมุมมองแบบบังคับซึ่งอิงตาม XML คอมโพสิเบิลต้องได้รับการบอกสถานะใหม่อย่างชัดเจนเพื่อให้อัปเดตตามนั้น
@Composable private fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField( value = "", onValueChange = { }, label = { Text("Name") } ) } }
หากเรียกใช้และพยายามป้อนข้อความ คุณจะเห็นว่าไม่มีอะไรเกิดขึ้น เนื่องจาก TextField
จะไม่อัปเดตเอง แต่อัปเดตเมื่อพารามิเตอร์ value
เปลี่ยนแปลง ปัญหานี้เกิดจากวิธีการทำงานของการจัดองค์ประกอบและการจัดองค์ประกอบใหม่ใน Compose
ดูข้อมูลเพิ่มเติมเกี่ยวกับการเขียนแบบร่างครั้งแรกและการเขียนแบบร่างอีกครั้งได้ที่การคิดในเครื่องมือเขียน
สถานะในคอมโพสิเบิล
ฟังก์ชันคอมโพสิเบิลสามารถใช้ remember
API เพื่อจัดเก็บออบเจ็กต์ในหน่วยความจำ ระบบจะจัดเก็บค่าที่คำนวณโดย remember
ไว้ในองค์ประกอบระหว่างการจัดองค์ประกอบครั้งแรก และระบบจะแสดงผลค่าที่เก็บไว้ระหว่างการจัดองค์ประกอบอีกครั้ง
remember
ใช้จัดเก็บทั้งออบเจ็กต์ที่เปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้
mutableStateOf
สร้าง Observable
MutableState<T>
ซึ่งเป็นประเภท Observable ที่ผสานรวมกับรันไทม์ของ Compose
interface MutableState<T> : State<T> {
override var value: T
}
การเปลี่ยนแปลงใดๆ ใน value
จะกำหนดเวลาการจัดเรียงใหม่ของฟังก์ชันแบบคอมโพสิเบิลที่อ่าน value
การประกาศออบเจ็กต์ MutableState
ในคอมโพสิเบิลทำได้ 3 วิธีดังนี้
val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
การประกาศเหล่านี้เทียบเท่ากันและจัดเตรียมไว้เป็นไวยากรณ์ทางเลือกสำหรับการใช้สถานะที่แตกต่างกัน คุณควรเลือกรูปแบบที่ผลิตโค้ดที่อ่านง่ายที่สุดในคอมโพสิเบิลที่คุณเขียน
ไวยากรณ์ by
ของ Delegate ต้องมีการนําเข้าต่อไปนี้
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
คุณสามารถใช้ค่าที่บันทึกไว้เป็นพารามิเตอร์สําหรับคอมโพสิเบิลอื่นๆ หรือแม้แต่เป็นตรรกะในคำสั่งเพื่อเปลี่ยนคอมโพสิเบิลที่จะแสดง ตัวอย่างเช่น หากไม่ต้องการให้แสดงคําทักทายหากชื่อว่างเปล่า ให้ใช้สถานะในif
คำสั่ง ดังนี้
@Composable fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { var name by remember { mutableStateOf("") } if (name.isNotEmpty()) { Text( text = "Hello, $name!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) } }
แม้ว่า remember
จะช่วยรักษาสถานะไว้ระหว่างการคอมโพสใหม่ แต่สถานะดังกล่าวจะไม่ได้รับการเก็บรักษาไว้เมื่อมีการทําการเปลี่ยนแปลงการกําหนดค่า ในกรณีนี้ คุณต้องใช้ rememberSaveable
rememberSaveable
จะบันทึกค่าที่บันทึกได้ใน Bundle
โดยอัตโนมัติ สําหรับค่าอื่นๆ คุณสามารถส่งออบเจ็กต์โปรแกรมช่วยบันทึกที่กําหนดเองได้
สถานะประเภทอื่นๆ ที่รองรับ
คอมโพซไม่จําเป็นต้องใช้ MutableState<T>
เพื่อเก็บสถานะ แต่รองรับประเภทอื่นๆ ที่สังเกตได้ ก่อนอ่านประเภทที่สังเกตได้อื่นใน Compose คุณต้องแปลงเป็น State<T>
เพื่อให้คอมโพสิเบิลคอมไพล์ใหม่โดยอัตโนมัติเมื่อสถานะมีการเปลี่ยนแปลง
คอมโพสิชันเรือกับฟังก์ชันเพื่อสร้าง State<T>
จากประเภทที่สังเกตได้ทั่วไปซึ่งใช้ในแอป Android ก่อนใช้การผสานรวมเหล่านี้ ให้เพิ่มอาร์ติแฟกต์ที่เหมาะสมตามที่ระบุไว้ด้านล่าง
Flow
:collectAsStateWithLifecycle()
collectAsStateWithLifecycle()
จะรวบรวมค่าจากFlow
ในลักษณะที่คำนึงถึงวงจร ทำให้แอปของคุณประหยัดทรัพยากรได้ ค่านี้แสดงถึงค่าที่ส่งออกล่าสุดจากState
ของคอมโพสิชัน ใช้ API นี้เป็นวิธีที่แนะนําในการรวบรวมการไหลเวียนในแอป Androidต้องมีข้อกําหนดเบื้องต้นต่อไปนี้ในไฟล์
build.gradle
(ควรเป็น 2.6.0-beta01 ขึ้นไป)
Kotlin
dependencies {
...
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
}
Groovy
dependencies {
...
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.8.7"
}
-
collectAsState
คล้ายกับcollectAsStateWithLifecycle
เนื่องจากจะรวบรวมค่าจากFlow
และเปลี่ยนค่าดังกล่าวเป็น ComposeState
ด้วยใช้
collectAsState
สำหรับโค้ดที่ไม่ขึ้นอยู่กับแพลตฟอร์มแทนcollectAsStateWithLifecycle
ซึ่งใช้ได้กับ Android เท่านั้นcollectAsState
ไม่จำเป็นต้องใช้ทรัพยากรเพิ่มเติมเนื่องจากมีอยู่ในcompose-runtime
-
observeAsState()
เริ่มสังเกตLiveData
นี้และแสดงค่าผ่านState
ต้องมีข้อกําหนดเบื้องต้นต่อไปนี้ในไฟล์
build.gradle
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-livedata:1.7.5")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-livedata:1.7.5"
}
-
subscribeAsState()
คือฟังก์ชันส่วนขยายที่เปลี่ยนสตรีมแบบเรียลไทม์ของ RxJava2 (เช่นSingle
,Observable
,Completable
) ให้เป็น ComposeState
ต้องมีข้อกําหนดเบื้องต้นต่อไปนี้ในไฟล์
build.gradle
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava2:1.7.5")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava2:1.7.5"
}
-
subscribeAsState()
คือฟังก์ชันเสริมที่เปลี่ยนสตรีมแบบเรียลไทม์ของ RxJava3 (เช่นSingle
,Observable
,Completable
) เป็น ComposeState
ต้องมีข้อกําหนดเบื้องต้นต่อไปนี้ในไฟล์
build.gradle
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava3:1.7.5")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava3:1.7.5"
}
การเก็บสถานะกับการไม่เก็บสถานะ
คอมโพสิชันที่ใช้ remember
เพื่อจัดเก็บออบเจ็กต์จะสร้างสถานะภายใน ซึ่งทำให้คอมโพสิชันมีสถานะ HelloContent
เป็นตัวอย่างของคอมโพสิชันที่มีสถานะเนื่องจากเก็บและแก้ไขสถานะ name
ภายใน ซึ่งอาจมีประโยชน์ในสถานการณ์ที่ผู้โทรไม่จำเป็นต้องควบคุมสถานะและสามารถใช้งานได้โดยไม่ต้องจัดการสถานะด้วยตนเอง อย่างไรก็ตาม คอมโพสิเบิลที่มีสถานะภายในมักจะนํากลับมาใช้ซ้ำได้น้อยลงและทดสอบได้ยากขึ้น
คอมโพสิเบิลที่ไม่มีสถานะคือคอมโพสิเบิลที่ไม่มีสถานะใดๆ วิธีง่ายๆ ในการทำให้เป็นแบบไม่เก็บสถานะคือการใช้การยกสถานะ
เมื่อพัฒนาคอมโพสิเบิลแบบนํากลับมาใช้ซ้ำ คุณมักจะต้องการแสดงทั้งคอมโพสิเบิลเดียวกันเวอร์ชันที่มีสถานะและไม่มีสถานะ เวอร์ชันที่มีสถานะจะสะดวกสำหรับผู้เรียกที่ไม่สนใจสถานะ ส่วนเวอร์ชันที่ไม่มีสถานะจำเป็นสำหรับผู้เรียกที่ต้องการควบคุมหรือยกสถานะ
การย้ายสถานะ
การยกระดับสถานะใน Compose เป็นรูปแบบการย้ายสถานะไปยังผู้เรียกของคอมโพสิเบิลเพื่อทำให้เป็นคอมโพสิเบิลที่ไม่มีสถานะ รูปแบบทั่วไปสำหรับการยกระดับสถานะใน Compose ของ Jetpack คือการใช้พารามิเตอร์ 2 รายการแทนตัวแปรสถานะ ดังนี้
value: T
: ค่าปัจจุบันที่จะแสดงonValueChange: (T) -> Unit
: เหตุการณ์ที่ขอให้เปลี่ยนค่า โดยที่T
คือค่าใหม่ที่เสนอ
แต่คุณไม่จำเป็นต้องใช้ onValueChange
เท่านั้น หากเหตุการณ์ที่เฉพาะเจาะจงมากขึ้นเหมาะกับคอมโพสิเบิล คุณควรกําหนดเหตุการณ์เหล่านั้นโดยใช้ Lambda
สถานะที่ยกระดับด้วยวิธีนี้มีพร็อพเพอร์ตี้สำคัญบางอย่างดังนี้
- แหล่งข้อมูลที่เชื่อถือได้เพียงแหล่งเดียว: การย้ายสถานะแทนการทำซ้ำช่วยให้มั่นใจได้ว่าจะมีแหล่งข้อมูลที่เชื่อถือได้เพียงแหล่งเดียว วิธีนี้จะช่วยหลีกเลี่ยงข้อบกพร่อง
- Encapsulated: มีเพียงคอมโพสิเบิลที่มีสถานะเท่านั้นที่จะแก้ไขสถานะได้ การดำเนินการนี้เกิดขึ้นภายใน
- แชร์ได้: แชร์สถานะที่มีการยกระดับกับคอมโพสิเบิลหลายรายการได้ หากต้องการอ่าน
name
ในคอมโพสิเบิลอื่น การยกระดับจะช่วยให้คุณทําเช่นนั้นได้ - สามารถรับมือได้: ผู้เรียกใช้คอมโพสิเบิลแบบไม่มีสถานะสามารถเลือกที่จะเพิกเฉยหรือแก้ไขเหตุการณ์ก่อนที่จะเปลี่ยนสถานะได้
- แยกส่วน: สถานะของคอมโพสิเบิลที่ไม่มีสถานะอาจจัดเก็บไว้ที่ใดก็ได้ ตัวอย่างเช่น ตอนนี้คุณสามารถย้าย
name
ไปยังViewModel
ได้แล้ว
ในตัวอย่างนี้ คุณจะดึง name
และ onValueChange
ออกจาก HelloContent
แล้วย้ายขึ้นไปที่คอมโพสิเบิล HelloScreen
ที่เรียก HelloContent
@Composable fun HelloScreen() { var name by rememberSaveable { mutableStateOf("") } HelloContent(name = name, onNameChange = { name = it }) } @Composable fun HelloContent(name: String, onNameChange: (String) -> Unit) { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello, $name", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField(value = name, onValueChange = onNameChange, label = { Text("Name") }) } }
การยกสถานะออกจาก HelloContent
จะช่วยให้คุณหาเหตุผลเกี่ยวกับคอมโพสิเบิล นำมาใช้ซ้ำในสถานการณ์ต่างๆ และทำการทดสอบได้ง่ายขึ้น HelloContent
ไม่ได้เชื่อมโยงกับวิธีจัดเก็บสถานะ การแยกการเชื่อมโยงหมายความว่าหากแก้ไขหรือแทนที่ HelloScreen
คุณไม่จําเป็นต้องเปลี่ยนวิธีติดตั้งใช้งาน HelloContent
รูปแบบที่สถานะลดลงและเหตุการณ์เพิ่มขึ้นเรียกว่าการไหลของข้อมูลแบบทิศทางเดียว ในกรณีนี้ สถานะจะลดลงจาก HelloScreen
เป็น HelloContent
และเหตุการณ์จะเพิ่มขึ้นจาก HelloContent
เป็น HelloScreen
เมื่อใช้การไหลของข้อมูลแบบทิศทางเดียว คุณจะแยกคอมโพสิเบิลที่แสดงสถานะใน UI ออกจากส่วนต่างๆ ของแอปที่เก็บและเปลี่ยนแปลงสถานะได้
ดูข้อมูลเพิ่มเติมที่หน้าตําแหน่งที่จะแสดงสถานะ
การกู้คืนสถานะในคอมโพสิท
rememberSaveable
API มีลักษณะการทำงานคล้ายกับ remember
เนื่องจากจะเก็บสถานะไว้ตลอดการคอมโพสิชันใหม่ รวมถึงการทํากิจกรรมหรือการสร้างกระบวนการใหม่โดยใช้กลไกสถานะอินสแตนซ์ที่บันทึกไว้ ตัวอย่างเช่น กรณีนี้เกิดขึ้นเมื่อหมุนหน้าจอ
วิธีจัดเก็บสถานะ
ระบบจะบันทึกประเภทข้อมูลทั้งหมดที่เพิ่มลงใน Bundle
โดยอัตโนมัติ หากต้องการบันทึกสิ่งที่เพิ่มลงใน Bundle
ไม่ได้ คุณมีตัวเลือกหลายอย่าง
แบ่งแปลงที่ดิน
วิธีที่ง่ายที่สุดคือเพิ่มคำอธิบายประกอบ @Parcelize
ให้กับออบเจ็กต์ ออบเจ็กต์จะแบ่งออกเป็นส่วนๆ ได้และสามารถรวมกลุ่มได้ ตัวอย่างเช่น โค้ดนี้จะสร้างประเภทข้อมูล City
ที่แบ่งออกเป็นส่วนๆ และบันทึกลงในสถานะ
@Parcelize data class City(val name: String, val country: String) : Parcelable @Composable fun CityScreen() { var selectedCity = rememberSaveable { mutableStateOf(City("Madrid", "Spain")) } }
MapSaver
หาก @Parcelize
ไม่เหมาะด้วยเหตุผลบางประการ คุณสามารถใช้ mapSaver
เพื่อกำหนดกฎของคุณเองสำหรับการแปลงออบเจ็กต์เป็นชุดค่าที่ระบบจะบันทึกลงใน Bundle
ได้
data class City(val name: String, val country: String) val CitySaver = run { val nameKey = "Name" val countryKey = "Country" mapSaver( save = { mapOf(nameKey to it.name, countryKey to it.country) }, restore = { City(it[nameKey] as String, it[countryKey] as String) } ) } @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
ListSaver
หากไม่ต้องการกำหนดคีย์สําหรับแผนที่ คุณสามารถใช้ listSaver
และใช้ดัชนีเป็นคีย์ได้ ดังนี้
data class City(val name: String, val country: String) val CitySaver = listSaver<City, Any>( save = { listOf(it.name, it.country) }, restore = { City(it[0] as String, it[1] as String) } ) @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
ตัวเก็บสถานะในคอมโพซ
คุณสามารถจัดการการยกระดับสถานะแบบง่ายในฟังก์ชันคอมโพสิเบิลได้ อย่างไรก็ตาม หากสถานะที่จะติดตามมีจำนวนเพิ่มขึ้น หรือมีตรรกะที่จะดำเนินการในฟังก์ชันคอมโพสิเบิล แนวทางปฏิบัติแนะนำคือการมอบหมายความรับผิดชอบด้านตรรกะและสถานะให้กับคลาสอื่นๆ ซึ่งก็คือผู้ถือสถานะ
ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับการยกระดับสถานะใน Compose หรือดูข้อมูลทั่วไปได้ในหน้าตัวเก็บสถานะและสถานะ UI ในคู่มือสถาปัตยกรรม
เรียกใช้การคํานวณการจดจําอีกครั้งเมื่อคีย์มีการเปลี่ยนแปลง
remember
API มักใช้ร่วมกับ MutableState
ดังนี้
var name by remember { mutableStateOf("") }
ในตัวอย่างนี้ การใช้ฟังก์ชัน remember
ทําให้ค่า MutableState
อยู่รอดได้แม้จะมีการเปลี่ยนรูปแบบ
โดยทั่วไป remember
จะใช้พารามิเตอร์ Lambda calculation
เมื่อเรียกใช้ remember
เป็นครั้งแรก ระบบจะเรียกใช้ Lambda ของ calculation
และจัดเก็บผลลัพธ์ ในระหว่างการจัดเรียงใหม่ remember
จะแสดงค่าที่เก็บไว้ล่าสุด
นอกจากการแคชสถานะแล้ว คุณยังใช้ remember
เพื่อจัดเก็บออบเจ็กต์หรือผลลัพธ์ของการดำเนินการในคอมโพสิชันที่ใช้เวลาในการเริ่มต้นหรือคำนวณนานได้ด้วย คุณอาจไม่ต้องการทําการคํานวณนี้ซ้ำทุกครั้งที่เปลี่ยนการผสม
ตัวอย่างเช่น การสร้างออบเจ็กต์ ShaderBrush
นี้ ซึ่งเป็นการดำเนินการที่มีค่าใช้จ่ายสูง
val brush = remember { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) }
remember
จะจัดเก็บค่าไว้จนกว่าค่านั้นจะออกจากการคอมโพสิชัน อย่างไรก็ตาม มีวิธีทำให้ค่าที่แคชไว้เป็นค่าที่ไม่ถูกต้อง นอกจากนี้ remember
API ยังใช้พารามิเตอร์ key
หรือ
keys
ด้วย หากคีย์ใดคีย์หนึ่งเหล่านี้มีการเปลี่ยนแปลง ครั้งถัดไปที่ฟังก์ชันคอมไพล์ใหม่ remember
จะลบล้างแคชและดำเนินการคำนวณในบล็อก lambda อีกครั้ง กลไกนี้ช่วยให้คุณควบคุมอายุการใช้งานของออบเจ็กต์ในคอมโพสิชันได้ การคํานวณจะยังคงใช้งานได้จนกว่าอินพุตจะเปลี่ยนแปลง ไม่ใช่จนกว่าค่าที่จดจําไว้จะออกจากการคอมโพสิชัน
ตัวอย่างต่อไปนี้แสดงวิธีการทํางานของกลไกนี้
ในข้อมูลโค้ดนี้ ระบบจะสร้าง ShaderBrush
และใช้เป็นการวาดพื้นหลังของคอมโพสิเบิล Box
remember
จะจัดเก็บอินสแตนซ์ ShaderBrush
ไว้เนื่องจากการสร้างใหม่มีค่าใช้จ่ายสูง ตามที่อธิบายไว้ก่อนหน้านี้ remember
ใช้ avatarRes
เป็นพารามิเตอร์ key1
ซึ่งเป็นภาพพื้นหลังที่เลือก หากavatarRes
มีการเปลี่ยนแปลง แปรงจะจัดองค์ประกอบใหม่ด้วยรูปภาพใหม่และนำไปใช้กับBox
อีกครั้ง กรณีนี้อาจเกิดขึ้นเมื่อผู้ใช้เลือกรูปภาพอื่นเป็นพื้นหลังจากเครื่องมือเลือก
@Composable private fun BackgroundBanner( @DrawableRes avatarRes: Int, modifier: Modifier = Modifier, res: Resources = LocalContext.current.resources ) { val brush = remember(key1 = avatarRes) { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) } Box( modifier = modifier.background(brush) ) { /* ... */ } }
ในข้อมูลโค้ดต่อไปนี้ ระบบจะยกสถานะไปยังคลาสตัวเก็บสถานะแบบธรรมดา
MyAppState
โดยจะแสดงฟังก์ชัน rememberMyAppState
เพื่อเริ่มต้นอินสแตนซ์ของคลาสโดยใช้ remember
การแสดงฟังก์ชันดังกล่าวเพื่อสร้างอินสแตนซ์ที่ยังคงอยู่หลังจากการคอมโพสิชันใหม่เป็นรูปแบบที่พบได้ทั่วไปใน Compose ฟังก์ชัน rememberMyAppState
ได้รับ windowSizeClass
ซึ่งทำหน้าที่เป็นพารามิเตอร์ key
สำหรับ remember
หากพารามิเตอร์นี้เปลี่ยนแปลง แอปจะต้องสร้างคลาสตัวเก็บสถานะแบบธรรมดาขึ้นมาใหม่โดยใช้ค่าล่าสุด กรณีนี้อาจเกิดขึ้นได้หากผู้ใช้หมุนอุปกรณ์ เป็นต้น
@Composable private fun rememberMyAppState( windowSizeClass: WindowSizeClass ): MyAppState { return remember(windowSizeClass) { MyAppState(windowSizeClass) } } @Stable class MyAppState( private val windowSizeClass: WindowSizeClass ) { /* ... */ }
Compose ใช้การใช้งาน equals ของคลาสเพื่อตัดสินใจว่าคีย์มีการเปลี่ยนแปลงหรือไม่และทำให้ค่าที่เก็บไว้เป็นโมฆะ
จัดเก็บสถานะด้วยคีย์นอกเหนือจากการจัดเรียงใหม่
rememberSaveable
API คือ Wrapper ของ remember
ที่สามารถจัดเก็บข้อมูลใน Bundle
API นี้ช่วยให้สถานะอยู่รอดได้ไม่เพียงต่อการคอมโพสิชันใหม่เท่านั้น แต่ยังรวมถึงการสร้างกิจกรรมใหม่และการสิ้นสุดกระบวนการที่ระบบเริ่ม
rememberSaveable
ได้รับพารามิเตอร์ input
เพื่อวัตถุประสงค์เดียวกันกับที่
remember
ได้รับ keys
แคชจะใช้งานไม่ได้เมื่อข้อมูลใดๆ เปลี่ยนแปลง เมื่อฟังก์ชันคอมไพล์ใหม่ครั้งถัดไป rememberSaveable
จะเรียกใช้บล็อก LAMBDA การคํานวณอีกครั้ง
ในตัวอย่างต่อไปนี้ rememberSaveable
จะจัดเก็บ userTypedQuery
จนกว่า typedQuery
จะเปลี่ยนแปลง
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
ดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับสถานะและ Jetpack Compose ได้จากแหล่งข้อมูลเพิ่มเติมต่อไปนี้
ตัวอย่าง
Codelabs
วิดีโอ
บล็อก
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การจัดโครงสร้าง UI ของ Compose
- บันทึกสถานะ UI ใน Compose
- ผลข้างเคียงในโหมดเขียน