UI ใน Compose จะเปลี่ยนแปลงไม่ได้และจะไม่มีการอัปเดตหลังจากอัปเดตแล้ว
วาด สิ่งที่คุณควบคุมได้คือสถานะของ UI ทุกครั้งที่สถานะของ
การเปลี่ยนแปลง UI, Compose จะสร้างส่วนของโครงสร้าง UI ที่มี
มีการเปลี่ยนแปลง Composable ยอมรับได้
สถานะและแสดงเหตุการณ์ เช่น TextField
จะยอมรับค่าและแสดง
Callback onValueChange
ที่ขอเครื่องจัดการ Callback เพื่อเปลี่ยน
var name by remember { mutableStateOf("") } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } )
เนื่องจาก Composable จะยอมรับสถานะและแสดงเหตุการณ์ โฟลว์ข้อมูลที่เป็นทิศทางเดียวกัน รูปแบบเข้ากันได้ดีกับ Jetpack Compose คู่มือนี้เน้นวิธีติดตั้งใช้งาน รูปแบบโฟลว์ข้อมูลแบบทิศทางเดียวในการเขียน วิธีใช้งานเหตุการณ์ เจ้าของสถานะ และวิธีทำงานกับ ViewModels ใน Compose
การรับส่งข้อมูลแบบทิศทางเดียว
โฟลว์ข้อมูลแบบทิศทางเดียว (UDF) เป็นรูปแบบการออกแบบที่รัฐจะไหลลง และเหตุการณ์ต่างๆ จะไหลลื่นขึ้น เมื่อทำตามโฟลว์ข้อมูลที่ไปในทิศทางเดียวกัน คุณจะแยกส่วน Composable ที่แสดงสถานะใน UI จากส่วนต่างๆ ของแอปที่จัดเก็บ และเปลี่ยนสถานะ
ลูปการอัปเดต UI สำหรับแอปที่ใช้โฟลว์ข้อมูลแบบทิศทางเดียวจะมีลักษณะดังนี้
- กิจกรรม: ส่วนหนึ่งของ UI จะสร้างกิจกรรมและส่งต่อขึ้นด้านบน เช่น ส่งการคลิกปุ่มไปยัง ViewModel เพื่อจัดการ หรือเหตุการณ์ได้รับการส่งผ่าน อื่นๆ ของแอป เช่น การระบุว่าเซสชันของผู้ใช้ หมดอายุแล้ว
- สถานะการอัปเดต: เครื่องจัดการเหตุการณ์อาจเปลี่ยนสถานะ
- สถานะการแสดงผล: เจ้าของสถานะข้ามสถานะไป และ UI จะแสดงขึ้น ได้
![](https://developer.android.com/static/develop/ui/compose/images/state-unidirectional-flow.png?authuser=5&hl=th)
รูปแบบต่อไปนี้เมื่อใช้ Jetpack Compose มีข้อดีหลายประการดังนี้
- ความสามารถในการทดสอบ: การแยกสถานะจาก UI ที่แสดงช่วยให้ดำเนินการได้ง่ายขึ้น เพื่อทดสอบทั้ง 2 แบบแยกกัน
- การสรุปสถานะ: เนื่องจากสามารถอัปเดตสถานะได้ในที่เดียวและ มีแหล่งข้อมูลที่ถูกต้องเพียงแหล่งเดียวสำหรับสถานะของ Composable ซึ่งน้อยกว่า คุณอาจจะสร้างข้อบกพร่องจากสถานะที่ไม่สอดคล้องกัน
- ความสอดคล้องของ UI: การอัปเดตสถานะทั้งหมดจะแสดงใน UI ทันทีโดย
การใช้เจ้าของสถานะที่สังเกตได้ เช่น
StateFlow
หรือLiveData
การรับส่งข้อมูลแบบทิศทางเดียวใน Jetpack Compose
Composable จะทำงานตามสถานะและเหตุการณ์ ตัวอย่างเช่น TextField
จะมีเพียง
อัปเดตเมื่ออัปเดตพารามิเตอร์ value
และแสดง onValueChange
Callback — เหตุการณ์ที่มีการขอให้เปลี่ยนค่าเป็นค่าใหม่ เขียน
กำหนดออบเจ็กต์ State
เป็นที่เก็บค่า และเปลี่ยนเป็นค่าสถานะ
ก็จะทำให้เกิดการจัดองค์ประกอบใหม่ คุณสามารถเก็บสถานะใน
remember { mutableStateOf(value) }
หรือ
rememberSaveable { mutableStateOf(value)
ขึ้นอยู่กับระยะเวลาที่ต้องการ
ให้จดจำค่าสำหรับ
ประเภทของค่า Composable ของ TextField
คือ String
จะได้มา
จากทุกที่ - จากค่าแบบฮาร์ดโค้ด, จาก ViewModel หรือส่งจาก
Composable หลัก คุณไม่จำเป็นต้องเก็บบัตรไว้ในออบเจ็กต์ State
แต่ต้องมี
เพื่ออัปเดตค่าเมื่อมีการเรียก onValueChange
กำหนดพารามิเตอร์ที่ประกอบกันได้
เมื่อกำหนดพารามิเตอร์สถานะของ Composable คุณควรเก็บค่าต่อไปนี้ คำถามเหล่านี้
- Composable สามารถใช้ซ้ำได้หรือยืดหยุ่นมากน้อยเพียงใด
- พารามิเตอร์สถานะส่งผลต่อประสิทธิภาพของ Composable นี้อย่างไร
Composable แต่ละรายการควรมีปริมาณน้อยที่สุดเพื่อกระตุ้นให้เกิดการแยกและนำกลับมาใช้ใหม่ ข้อมูลเท่าที่จะเป็นไปได้ ตัวอย่างเช่น เมื่อสร้าง Composable เพื่อเก็บ ในส่วนหัวของบทความข่าว ต้องการให้ส่งเฉพาะข้อมูลที่จำเป็นต้อง แทนบทความข่าวทั้งหมด
@Composable fun Header(title: String, subtitle: String) { // Recomposes when title or subtitle have changed. } @Composable fun Header(news: News) { // Recomposes when a new instance of News is passed in. }
บางครั้ง การใช้พารามิเตอร์เดี่ยวๆ ก็ช่วยเพิ่มประสิทธิภาพได้ เช่น หาก
News
มีข้อมูลมากกว่าแค่ title
และ subtitle
มีการส่งอินสแตนซ์ใหม่ของ News
ไปยัง Header(news)
องค์ประกอบ Composable จะ
เขียนใหม่แม้ว่า title
และ subtitle
จะไม่มีการเปลี่ยนแปลง
พิจารณาจํานวนพารามิเตอร์ที่ส่งอย่างรอบคอบ การใช้ฟังก์ชัน การมีพารามิเตอร์มากเกินไปจะทำให้ฟังก์ชันลดลงตามหลักการยศาสตร์ ดังนั้นในกรณีนี้ ขอแนะนำให้จัดกลุ่มนักเรียนในชั้นเรียน
เหตุการณ์ใน Compose
การป้อนข้อมูลทุกรายการในแอปควรแสดงเป็นเหตุการณ์ เช่น การแตะ การเปลี่ยนแปลงข้อความ
และแม้แต่ตัวจับเวลาหรือการอัปเดตอื่นๆ เมื่อเหตุการณ์เหล่านี้เปลี่ยนสถานะ UI ของคุณ
ViewModel
ควรเป็นหน้าจัดการและอัปเดตสถานะ UI
เลเยอร์ UI ไม่ควรเปลี่ยนสถานะภายนอกตัวแฮนเดิลเหตุการณ์เนื่องจาก อาจทำให้เกิดความไม่สอดคล้องกันและข้อบกพร่องในแอปพลิเคชันของคุณ
ต้องการส่งค่าที่เปลี่ยนแปลงไม่ได้สำหรับ lambda เครื่องจัดการสถานะและเหตุการณ์ ช่วงเวลานี้ มีประโยชน์ดังต่อไปนี้
- ช่วยให้คุณนำกลับมาใช้ใหม่ได้
- โปรดตรวจสอบว่า UI ไม่ได้เปลี่ยนค่าของรัฐโดยตรง
- หลีกเลี่ยงปัญหาการเกิดขึ้นพร้อมกันเนื่องจากคุณตรวจสอบว่ารัฐไม่ได้ เปลี่ยนแปลงมาจากชุดข้อความอื่น
- โดยมากช่วยลดความซับซ้อนของโค้ด
ตัวอย่างเช่น Composable ที่ยอมรับ String
และ lambda เป็นพารามิเตอร์ได้
สามารถเรียกได้จากหลายบริบทและนำมาใช้ซ้ำได้ สมมติว่าแอปยอดนิยม
ในแอปของคุณจะแสดงข้อความเสมอและมีปุ่มย้อนกลับ คุณสามารถกำหนด
ทั่วไป MyAppTopAppBar
Composable ที่รับข้อความและด้านหลัง
แฮนเดิลเป็นพารามิเตอร์
@Composable fun MyAppTopAppBar(topAppBarText: String, onBackPressed: () -> Unit) { TopAppBar( title = { Text( text = topAppBarText, textAlign = TextAlign.Center, modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) }, navigationIcon = { IconButton(onClick = onBackPressed) { Icon( Icons.Filled.ArrowBack, contentDescription = localizedString ) } }, // ... ) }
ViewModels, สถานะ และเหตุการณ์: ตัวอย่าง
การใช้ ViewModel
และ mutableStateOf
ช่วยให้คุณสามารถใช้ข้อมูลที่เป็นทิศทางเดียวกัน
ในแอป หากเป็นไปตามเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้
- สถานะของ UI จะแสดงผ่านค่าสถานะที่สังเกตได้ เช่น
StateFlow
หรือLiveData
ViewModel
จะจัดการเหตุการณ์ที่มาจาก UI หรือเลเยอร์อื่นๆ ของแอป และอัปเดตเจ้าของรัฐตามเหตุการณ์
เช่น เมื่อใช้งานหน้าจอลงชื่อเข้าใช้ ให้แตะปุ่มลงชื่อเข้าใช้ จะทำให้แอปแสดงไอคอนหมุนแสดงความคืบหน้าและการเรียกใช้เครือข่าย หาก เข้าสู่ระบบสำเร็จ จากนั้นแอปของคุณจะไปยังหน้าจออื่น ในกรณีที่ ข้อผิดพลาดที่แอปแสดง Snackbar ต่อไปนี้คือวิธีที่คุณจะจำลองสถานะหน้าจอ และกิจกรรม
หน้าจอจะมี 4 สถานะดังนี้
- ออกจากระบบ: เมื่อผู้ใช้ยังไม่ได้ลงชื่อเข้าใช้
- อยู่ระหว่างดำเนินการ: เมื่อแอปของคุณพยายามให้ผู้ใช้ลงชื่อเข้าใช้ภายใน กำลังเรียกใช้เครือข่าย
- ข้อผิดพลาด: เมื่อเกิดข้อผิดพลาดขณะลงชื่อเข้าใช้
- ลงชื่อเข้าใช้: เมื่อผู้ใช้ลงชื่อเข้าใช้
คุณสร้างโมเดลรัฐเหล่านี้เป็นคลาสที่ปิดผนึกได้ ViewModel
จะแสดงสถานะเป็น
State
ตั้งค่าสถานะเริ่มต้นและอัปเดตสถานะตามต้องการ
ViewModel
ยังจัดการเหตุการณ์การลงชื่อเข้าใช้ด้วยการแสดงเมธอด onSignIn()
class MyViewModel : ViewModel() { private val _uiState = mutableStateOf<UiState>(UiState.SignedOut) val uiState: State<UiState> get() = _uiState // ... }
นอกเหนือจาก mutableStateOf
API แล้ว Compose ยังมี
ส่วนขยายสำหรับ LiveData
, Flow
และ
Observable
เพื่อลงทะเบียนเป็น Listener และแสดงค่าเป็นสถานะ
class MyViewModel : ViewModel() { private val _uiState = MutableLiveData<UiState>(UiState.SignedOut) val uiState: LiveData<UiState> get() = _uiState // ... } @Composable fun MyComposable(viewModel: MyViewModel) { val uiState = viewModel.uiState.observeAsState() // ... }
ดูข้อมูลเพิ่มเติม
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับสถาปัตยกรรมใน Jetpack Compose โปรดดูแหล่งข้อมูลต่อไปนี้
ตัวอย่าง
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- State และ Jetpack Compose
- บันทึกสถานะ UI ใน Compose
- จัดการข้อมูลจากผู้ใช้