Jetpack Compose เป็นชุดเครื่องมือ UI สมัยใหม่ที่อธิบายอย่างชัดเจนสำหรับ Android Compose ช่วยให้การเขียนและดูแลรักษา UI ของแอปเป็นเรื่องง่ายด้วยการมอบ API แบบประกาศสิ่งที่ต้องการ ซึ่งช่วยให้คุณแสดงผล UI ของแอปได้โดยไม่ต้องเปลี่ยนแปลงมุมมองส่วนหน้าอย่างชัดเจน คำศัพท์นี้อาจต้องมีการอธิบายเพิ่มเติม แต่ผลที่ตามมานั้นสำคัญต่อการออกแบบแอป
กระบวนทัศน์การเขียนโปรแกรมแบบประกาศสิ่งที่ต้องการ
ในอดีต ลำดับชั้นการแสดงผลของ Android สามารถแสดงเป็นแผนผังของวิดเจ็ต UI ได้ เมื่อสถานะของแอปเปลี่ยนแปลงไปเนื่องจากสิ่งต่างๆ เช่น การโต้ตอบของผู้ใช้ ลำดับชั้นของ UI จะต้องได้รับการอัปเดตเพื่อแสดงข้อมูลปัจจุบัน
วิธีที่ใช้กันมากที่สุดในการอัปเดต UI คือการเดินผ่านแผนผังโดยใช้ฟังก์ชันต่างๆ เช่น
findViewById() และเปลี่ยน
โหนดโดยการเรียกใช้เมธอดต่างๆ เช่น button.setText(String),
container.addChild(View) หรือ img.setImageBitmap(Bitmap) เมธอดเหล่านี้จะเปลี่ยนสถานะภายในของวิดเจ็ต
การจัดการมุมมองด้วยตนเองจะเพิ่มโอกาสที่จะเกิดข้อผิดพลาด หากมีการแสดงผลข้อมูลในหลายๆ ที่ คุณอาจลืมอัปเดตมุมมองใดมุมมองหนึ่งที่แสดงข้อมูลนั้น นอกจากนี้ยังอาจทำให้เกิดสถานะที่ไม่ถูกต้องเมื่อการอัปเดต 2 รายการขัดแย้งกันในลักษณะที่ไม่คาดคิด เช่น การอัปเดตอาจพยายามตั้งค่าโหนดที่เพิ่งนำออกจาก UI โดยทั่วไป ความซับซ้อนในการบำรุงรักษาซอฟต์แวร์จะเพิ่มขึ้นตามจำนวนมุมมองที่ต้องได้รับการอัปเดต
ในช่วงหลายปีที่ผ่านมา อุตสาหกรรมทั้งหมดได้เริ่มเปลี่ยนไปใช้โมเดล UI แบบประกาศสิ่งที่ต้องการ โมเดลนี้ช่วยลดความซับซ้อนในการสร้างและอัปเดตอินเทอร์เฟซผู้ใช้ เทคนิคนี้ทำงานโดยการสร้างหน้าจอทั้งหมดขึ้นมาใหม่ตั้งแต่ต้นในเชิงแนวคิด จากนั้นจึงใช้เฉพาะการเปลี่ยนแปลงที่จำเป็น แนวทางนี้ช่วยหลีกเลี่ยงความซับซ้อนในการอัปเดตลำดับชั้นการแสดงผลที่เก็บสถานะด้วยตนเอง Compose เป็นเฟรมเวิร์ก UI แบบประกาศสิ่งที่ต้องการ
ความท้าทายอย่างหนึ่งในการสร้างหน้าจอทั้งหมดขึ้นมาใหม่คืออาจใช้ทรัพยากรมากในแง่ของเวลา พลังการประมวลผล และการใช้งานแบตเตอรี่ Compose จึงเลือกส่วนต่างๆ ของ UI ที่ต้องวาดใหม่ได้อย่างชาญฉลาดในแต่ละครั้งเพื่อลดค่าใช้จ่ายนี้ ซึ่งส่งผลต่อวิธีที่คุณออกแบบ คอมโพเนนต์ UI ดังที่กล่าวไว้ในส่วนการจัดองค์ประกอบใหม่
ตัวอย่างฟังก์ชันที่ประกอบกันได้
เมื่อใช้ Compose คุณสามารถสร้างอินเทอร์เฟซผู้ใช้ได้โดยการกำหนดชุดฟังก์ชันที่ประกอบกันได้ ซึ่งรับข้อมูลและส่งองค์ประกอบ UI ตัวอย่างเช่น วิดเจ็ต Greeting ซึ่งรับ String และส่งวิดเจ็ต Text ที่แสดงข้อความทักทาย
สิ่งสำคัญบางอย่างเกี่ยวกับฟังก์ชันนี้
- คำอธิบายประกอบ: ฟังก์ชันนี้มีคำอธิบายประกอบ
@Composableฟังก์ชันที่ประกอบกันได้ทั้งหมดต้องมีคำอธิบายประกอบนี้ คำอธิบายประกอบนี้จะแจ้งให้คอมไพเลอร์ Compose ทราบว่าฟังก์ชันนี้มีไว้เพื่อแปลงข้อมูลเป็น UI - อินพุตข้อมูล: ฟังก์ชันนี้รับข้อมูล ฟังก์ชันที่ประกอบกันได้สามารถรับพารามิเตอร์ ซึ่งช่วยให้ตรรกะของแอปอธิบาย UI ได้ ในกรณีนี้ วิดเจ็ตของเรายอมรับ
Stringเพื่อให้ทักทายผู้ใช้ตามชื่อได้ - การแสดงผล UI: ฟังก์ชันนี้แสดงข้อความใน UI โดยจะเรียกใช้ฟังก์ชันที่ประกอบกันได้
Text()ซึ่งสร้างองค์ประกอบ UI ของข้อความขึ้นมาจริงๆ ฟังก์ชันที่ประกอบกันได้จะส่งลำดับชั้นของ UI โดยการเรียกใช้ฟังก์ชันที่ประกอบกันได้อื่นๆ - ไม่มีค่าที่แสดงผล: ฟังก์ชันนี้ไม่แสดงผลสิ่งใด ฟังก์ชัน Compose ที่ส่ง UI ไม่จำเป็นต้องแสดงผลสิ่งใด เนื่องจากฟังก์ชันเหล่านี้อธิบายสถานะหน้าจอเป้าหมายแทนที่จะสร้างวิดเจ็ต UI
คุณสมบัติ: ฟังก์ชันนี้รวดเร็ว ไม่มีการเปลี่ยนแปลงสถานะ และไม่มี ผลข้างเคียง
- ฟังก์ชันนี้ทำงานในลักษณะเดียวกันเมื่อเรียกใช้หลายครั้งด้วยอาร์กิวเมนต์เดียวกัน และไม่ได้ใช้ค่าอื่นๆ เช่น ตัวแปรส่วนกลางหรือการเรียกใช้
random() - ฟังก์ชันนี้อธิบาย UI โดยไม่มีผลข้างเคียง เช่น การแก้ไขพร็อพเพอร์ตี้หรือตัวแปรส่วนกลาง
โดยทั่วไป ฟังก์ชันที่ประกอบกันได้ทั้งหมดต้องเขียนด้วยคุณสมบัติเหล่านี้ ด้วยเหตุผลที่กล่าวไว้ในส่วนการจัดองค์ประกอบใหม่
- ฟังก์ชันนี้ทำงานในลักษณะเดียวกันเมื่อเรียกใช้หลายครั้งด้วยอาร์กิวเมนต์เดียวกัน และไม่ได้ใช้ค่าอื่นๆ เช่น ตัวแปรส่วนกลางหรือการเรียกใช้
การเปลี่ยนแปลงกระบวนทัศน์แบบประกาศสิ่งที่ต้องการ
ชุดเครื่องมือ UI แบบอิงตามออบเจ็กต์ที่จำเป็นต้องระบุหลายรายการ คุณจะเริ่มต้น UI โดยการสร้างอินสแตนซ์ของแผนผังวิดเจ็ต ซึ่งมักจะทำโดยการขยายไฟล์เลย์เอาต์ XML วิดเจ็ตแต่ละรายการจะรักษาสถานะภายในของตัวเอง และแสดงเมธอด Getter และ Setter ที่ช่วยให้ตรรกะของแอปโต้ตอบกับวิดเจ็ตได้
ในแนวทางแบบประกาศสิ่งที่ต้องการของ Compose วิดเจ็ตจะไม่มีสถานะและไม่แสดงฟังก์ชัน Setter หรือ Getter อันที่จริงแล้ว ระบบไม่ได้แสดงวิดเจ็ตเป็นออบเจ็กต์
คุณอัปเดต UI โดยการเรียกใช้ฟังก์ชันที่ประกอบกันได้เดียวกันด้วยอาร์กิวเมนต์ที่ต่างกัน ซึ่งช่วยลดความซับซ้อนในการระบุสถานะให้กับรูปแบบสถาปัตยกรรม เช่น
a ViewModel ดังที่อธิบายไว้ใน
คู่มือสถาปัตยกรรมแอป จากนั้นฟังก์ชันที่ประกอบกันได้จะมีหน้าที่แปลงสถานะแอปพลิเคชันปัจจุบันเป็น UI ทุกครั้งที่ข้อมูลที่ได้รับอนุญาตให้สังเกตพฤติกรรมผู้ใช้ได้ได้รับการอัปเดต
เมื่อผู้ใช้โต้ตอบกับ UI, UI จะสร้างเหตุการณ์ต่างๆ เช่น onClick
เหตุการณ์เหล่านั้นควรแจ้งให้ตรรกะของแอปทราบ ซึ่งจะเปลี่ยนสถานะของแอปได้
เมื่อสถานะเปลี่ยนแปลง ระบบจะเรียกใช้ฟังก์ชันที่ประกอบกันได้อีกครั้งด้วยข้อมูลใหม่ ซึ่งทำให้องค์ประกอบ UI ได้รับการวาดใหม่ กระบวนการนี้เรียกว่า การจัดองค์ประกอบใหม่
เนื้อหาแบบไดนามิก
เนื่องจากฟังก์ชันที่ประกอบกันได้เขียนด้วย Kotlin แทนที่จะเป็น XML ฟังก์ชันเหล่านี้จึงมีความไดนามิกเหมือนกับโค้ด Kotlin อื่นๆ ตัวอย่างเช่น สมมติว่าคุณต้องการสร้าง UI ที่ทักทายรายชื่อผู้ใช้
@Composable fun Greeting(names: List<String>) { for (name in names) { Text("Hello $name") } }
ฟังก์ชันนี้รับรายชื่อและสร้างคำทักทายสำหรับผู้ใช้แต่ละราย
ฟังก์ชันที่ประกอบกันได้มีความซับซ้อนได้มาก คุณสามารถใช้คำสั่ง if เพื่อตัดสินใจว่าจะแสดงองค์ประกอบ UI ที่เฉพาะเจาะจงหรือไม่ คุณสามารถใช้ลูปได้ คุณสามารถเรียกใช้ฟังก์ชันตัวช่วยได้ คุณมีความยืดหยุ่นอย่างเต็มที่ในการใช้ภาษาพื้นฐาน
พลังและความยืดหยุ่นนี้เป็นข้อได้เปรียบที่สำคัญอย่างหนึ่งของ Jetpack Compose
การจัดองค์ประกอบใหม่
ในโมเดล UI แบบจำเป็นต้องระบุ หากต้องการเปลี่ยนวิดเจ็ต คุณจะเรียกใช้ Setter ในวิดเจ็ตเพื่อเปลี่ยนสถานะภายใน ใน Compose คุณจะเรียกใช้ฟังก์ชันที่ประกอบกันได้อีกครั้งด้วยข้อมูลใหม่ การทำเช่นนี้จะทำให้ฟังก์ชันได้รับการ จัดองค์ประกอบใหม่--วิดเจ็ต ที่ฟังก์ชันส่งจะได้รับการวาดใหม่ด้วยข้อมูลใหม่ หากจำเป็น เฟรมเวิร์ก Compose สามารถจัดองค์ประกอบใหม่เฉพาะคอมโพเนนต์ที่เปลี่ยนแปลงได้อย่างชาญฉลาด
ตัวอย่างเช่น ลองดูฟังก์ชันที่ประกอบกันได้ต่อไปนี้ซึ่งแสดงปุ่ม
@Composable fun ClickCounter(clicks: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("I've been clicked $clicks times") } }
ทุกครั้งที่คลิกปุ่ม ผู้เรียกจะอัปเดตค่าของ clicks
Compose จะเรียกใช้ Lambda ด้วยฟังก์ชัน Text อีกครั้งเพื่อแสดงค่าใหม่ กระบวนการนี้เรียกว่า การจัดองค์ประกอบใหม่ ฟังก์ชันอื่นๆ ที่ไม่ได้ขึ้นอยู่กับค่าจะไม่ได้รับการจัดองค์ประกอบใหม่
ดังที่กล่าวไว้ การจัดองค์ประกอบใหม่ของแผนผัง UI ทั้งหมดอาจใช้ทรัพยากรการประมวลผลมาก ซึ่งใช้พลังการประมวลผลและแบตเตอรี่ Compose แก้ปัญหานี้ด้วย การจัดองค์ประกอบใหม่ที่ชาญฉลาด นี้
การจัดองค์ประกอบใหม่คือกระบวนการเรียกใช้ฟังก์ชันที่ประกอบกันได้อีกครั้งเมื่ออินพุตเปลี่ยนแปลง เมื่อ Compose จัดองค์ประกอบใหม่ตามอินพุตใหม่ ระบบจะเรียกใช้เฉพาะฟังก์ชันหรือ Lambda ที่อาจมีการเปลี่ยนแปลง และข้ามฟังก์ชันหรือ Lambda อื่นๆ Compose จะจัดองค์ประกอบใหม่ได้อย่างมีประสิทธิภาพโดยการข้ามฟังก์ชันหรือ Lambda ที่มีพารามิเตอร์ไม่เปลี่ยนแปลง
อย่าพึ่งพาผลข้างเคียงจากการเรียกใช้ฟังก์ชันที่ประกอบกันได้ เนื่องจากระบบอาจข้ามการจัดองค์ประกอบใหม่ของฟังก์ชัน หากทำเช่นนั้น ผู้ใช้อาจพบลักษณะการทำงานที่แปลกและคาดเดาไม่ได้ในแอป ผลข้างเคียงคือการเปลี่ยนแปลงใดๆ ที่แอปส่วนอื่นๆ มองเห็นได้ ตัวอย่างเช่น การดำเนินการต่อไปนี้เป็นผลข้างเคียงที่เป็นอันตราย
- การเขียนลงในพร็อพเพอร์ตี้ของออบเจ็กต์ที่แชร์
- การอัปเดตออบเจ็กต์ที่สังเกตได้ใน
ViewModel - การอัปเดตค่ากำหนดที่แชร์
ระบบอาจเรียกใช้ฟังก์ชันที่ประกอบกันได้อีกครั้งบ่อยเท่ากับทุกเฟรม เช่น เมื่อมีการแสดงผลภาพเคลื่อนไหว ฟังก์ชันที่ประกอบกันได้ควรทำงานอย่างรวดเร็วเพื่อหลีกเลี่ยงการกระตุกระหว่างภาพเคลื่อนไหว หากคุณต้องดำเนินการที่ใช้ทรัพยากรมาก เช่น การอ่านจากค่ากำหนดที่แชร์ ให้ดำเนินการในโครูทีนเบื้องหลังและส่งผลลัพธ์ค่าไปยังฟังก์ชันที่ประกอบกันได้เป็นพารามิเตอร์
ตัวอย่างเช่น โค้ดนี้สร้างฟังก์ชันที่ประกอบกันได้เพื่ออัปเดตค่าใน SharedPreferences ฟังก์ชันที่ประกอบกันได้ไม่ควรอ่านหรือเขียนจากค่ากำหนดที่แชร์ด้วยตัวเอง แต่โค้ดนี้จะย้ายการอ่านและการเขียนไปยัง ViewModel ในโครูทีนเบื้องหลัง ตรรกะของแอปจะส่งค่าปัจจุบันพร้อม Callback เพื่อทริกเกอร์การอัปเดต
@Composable fun SharedPrefsToggle( text: String, value: Boolean, onValueChanged: (Boolean) -> Unit ) { Row { Text(text) Checkbox(checked = value, onCheckedChange = onValueChanged) } }
เอกสารนี้กล่าวถึงสิ่งต่างๆ ที่ควรทราบเมื่อใช้ Compose ดังนี้
- การจัดองค์ประกอบใหม่จะข้ามฟังก์ชันที่ประกอบกันได้และ Lambda ให้ได้มากที่สุด
- การจัดองค์ประกอบใหม่เป็นแบบมองโลกในแง่ดีและอาจถูกยกเลิก
- ระบบอาจเรียกใช้ฟังก์ชันที่ประกอบกันได้บ่อยมาก เช่น ทุกเฟรมของภาพเคลื่อนไหว
- ฟังก์ชันที่ประกอบกันได้สามารถเรียกใช้แบบขนานได้
- ฟังก์ชันที่ประกอบกันได้สามารถเรียกใช้ตามลำดับใดก็ได้
ส่วนต่อไปนี้จะครอบคลุมวิธีสร้างฟังก์ชันที่ประกอบกันได้เพื่อรองรับการจัดองค์ประกอบใหม่ ในทุกกรณี แนวทางปฏิบัติแนะนำคือการทำให้ฟังก์ชันที่ประกอบกันได้ทำงานอย่างรวดเร็ว ไม่มีการเปลี่ยนแปลงสถานะ และไม่มีผลข้างเคียง
การจัดองค์ประกอบใหม่จะข้ามให้ได้มากที่สุด
เมื่อส่วนต่างๆ ของ UI ไม่ถูกต้อง Compose จะพยายามจัดองค์ประกอบใหม่เฉพาะส่วนที่ต้องได้รับการอัปเดต ซึ่งหมายความว่าระบบอาจข้ามการเรียกใช้ฟังก์ชันที่ประกอบกันได้ของ Button รายการเดียวอีกครั้งโดยไม่เรียกใช้ฟังก์ชันที่ประกอบกันได้ที่อยู่สูงกว่าหรือต่ำกว่าในแผนผัง UI
ฟังก์ชันที่ประกอบกันได้และ Lambda ทุกรายการอาจจัดองค์ประกอบใหม่ด้วยตัวเอง ตัวอย่างต่อไปนี้แสดงวิธีที่การจัดองค์ประกอบใหม่สามารถข้ามองค์ประกอบบางอย่างเมื่อแสดงผลรายการ
/** * Display a list of names the user can click with a header */ @Composable fun NamePicker( header: String, names: List<String>, onNameClicked: (String) -> Unit ) { Column { // this will recompose when [header] changes, but not when [names] changes Text(header, style = MaterialTheme.typography.bodyLarge) HorizontalDivider() // LazyColumn is the Compose version of a RecyclerView. // The lambda passed to items() is similar to a RecyclerView.ViewHolder. LazyColumn { items(names) { name -> // When an item's [name] updates, the adapter for that item // will recompose. This will not recompose when [header] changes NamePickerItem(name, onNameClicked) } } } } /** * Display a single name the user can click. */ @Composable private fun NamePickerItem(name: String, onClicked: (String) -> Unit) { Text(name, Modifier.clickable(onClick = { onClicked(name) })) }
ขอบเขตเหล่านี้แต่ละขอบเขตอาจเป็นสิ่งเดียวที่เรียกใช้ระหว่างการจัดองค์ประกอบใหม่
Compose อาจข้ามไปยัง Lambda ของ Column โดยไม่เรียกใช้ฟังก์ชันที่ประกอบกันได้ระดับบนสุดเมื่อ header เปลี่ยนแปลง และเมื่อเรียกใช้ Column Compose อาจเลือกที่จะ
ข้ามรายการของ LazyColumn's หาก names ไม่เปลี่ยนแปลง
อีกครั้ง ฟังก์ชันที่ประกอบกันได้หรือ Lambda ทั้งหมดควรไม่มีผลข้างเคียง เมื่อคุณต้องดำเนินการที่มีผลข้างเคียง ให้ทริกเกอร์จาก Callback
การจัดองค์ประกอบใหม่เป็นแบบมองโลกในแง่ดี
การจัดองค์ประกอบใหม่จะเริ่มขึ้นเมื่อใดก็ตามที่ Compose คิดว่าพารามิเตอร์ของฟังก์ชันที่ประกอบกันได้อาจมีการเปลี่ยนแปลง การจัดองค์ประกอบใหม่เป็นแบบ มองโลกในแง่ดี ซึ่งหมายความว่า Compose คาดว่าจะจัดองค์ประกอบใหม่เสร็จก่อนที่พารามิเตอร์จะเปลี่ยนแปลงอีกครั้ง หากพารามิเตอร์ เปลี่ยนแปลง ก่อนที่การจัดองค์ประกอบใหม่จะเสร็จสิ้น Compose อาจยกเลิกการจัดองค์ประกอบใหม่และเริ่มการจัดองค์ประกอบใหม่ด้วยพารามิเตอร์ใหม่
เมื่อการจัดองค์ประกอบใหม่ถูกยกเลิก Compose จะทิ้งแผนผัง UI จากการจัดองค์ประกอบใหม่ หากคุณมีผลข้างเคียงที่ขึ้นอยู่กับการแสดงผล UI ระบบจะใช้ผลข้างเคียงแม้ว่าจะยกเลิกการจัดองค์ประกอบแล้วก็ตาม ซึ่งอาจทำให้สถานะแอปไม่สอดคล้องกัน
ตรวจสอบว่าฟังก์ชันที่ประกอบกันได้และ Lambda ทั้งหมดไม่มีการเปลี่ยนแปลงสถานะและไม่มีผลข้างเคียงเพื่อรองรับการจัดองค์ประกอบใหม่แบบมองโลกในแง่ดี
ระบบอาจเรียกใช้ฟังก์ชันที่ประกอบกันได้บ่อยมาก
ในบางกรณี ระบบอาจเรียกใช้ฟังก์ชันที่ประกอบกันได้ทุกเฟรมของภาพเคลื่อนไหว UI หากฟังก์ชันดำเนินการที่ใช้ทรัพยากรมาก เช่น การอ่านจากพื้นที่เก็บข้อมูลของอุปกรณ์ ฟังก์ชันนี้อาจทำให้ UI กระตุก
ตัวอย่างเช่น หากวิดเจ็ตพยายามอ่านการตั้งค่าอุปกรณ์ วิดเจ็ตอาจอ่านการตั้งค่าเหล่านั้นหลายร้อยครั้งต่อวินาที ซึ่งส่งผลเสียต่อประสิทธิภาพของแอป
หากฟังก์ชันที่ประกอบกันได้ต้องใช้ข้อมูล ให้กำหนดพารามิเตอร์สำหรับข้อมูลนั้น จากนั้นคุณสามารถย้ายงานที่ใช้ทรัพยากรมากไปยังเทรดอื่นนอกการจัดองค์ประกอบ และส่งค่าผลลัพธ์ไปยังฟังก์ชันที่ประกอบกันได้เป็นพารามิเตอร์โดยใช้ mutableStateOf หรือ LiveData
ฟังก์ชันที่ประกอบกันได้สามารถเรียกใช้แบบขนานได้
Compose สามารถเพิ่มประสิทธิภาพการจัดองค์ประกอบใหม่ได้โดยการเรียกใช้ฟังก์ชันที่ประกอบกันได้แบบขนาน ซึ่งจะช่วยให้ Compose ใช้ประโยชน์จากหลายคอร์ และเรียกใช้ฟังก์ชันที่ประกอบกันได้ซึ่งไม่ได้อยู่บนหน้าจอด้วยลำดับความสำคัญที่ต่ำกว่า
การเพิ่มประสิทธิภาพนี้หมายความว่าฟังก์ชันที่ประกอบกันได้อาจเรียกใช้ภายในพูลของเทรดเบื้องหลัง
หากฟังก์ชันที่ประกอบกันได้เรียกใช้ฟังก์ชันใน ViewModel Compose อาจเรียกใช้ฟังก์ชันนั้นจากหลายเทรดพร้อมกัน
ฟังก์ชันที่ประกอบกันได้ทั้งหมดควรไม่มีผลข้างเคียงเพื่อให้แน่ใจว่าแอปพลิเคชันทำงานอย่างถูกต้อง แต่ให้ทริกเกอร์ผลข้างเคียงจาก Callback เช่น onClick ซึ่งจะเรียกใช้ในเทรด UI เสมอ
เมื่อมีการเรียกใช้ฟังก์ชันที่ประกอบกันได้ การเรียกใช้อาจเกิดขึ้นในเทรดอื่นที่ไม่ใช่เทรดของผู้เรียก ซึ่งหมายความว่าควรหลีกเลี่ยงโค้ดที่แก้ไขตัวแปรใน Lambda ที่ประกอบกันได้ ทั้งเนื่องจากโค้ดดังกล่าวไม่ปลอดภัยต่อเทรด และเนื่องจากเป็นผลข้างเคียงที่ไม่อนุญาตของ Lambda ที่ประกอบกันได้
ตัวอย่างต่อไปนี้แสดงฟังก์ชันที่ประกอบกันได้ซึ่งแสดงรายการและจำนวนรายการ
@Composable fun ListComposable(myList: List<String>) { Row(horizontalArrangement = Arrangement.SpaceBetween) { Column { for (item in myList) { Text("Item: $item") } } Text("Count: ${myList.size}") } }
โค้ดนี้ไม่มีผลข้างเคียงและแปลงรายการอินพุตเป็น UI เป็นโค้ดที่ยอดเยี่ยมสำหรับการแสดงรายการขนาดเล็ก อย่างไรก็ตาม หากฟังก์ชันเขียนลงในตัวแปรภายใน โค้ดนี้จะไม่ปลอดภัยต่อเทรดหรือถูกต้อง
@Composable fun ListWithBug(myList: List<String>) { var items = 0 Row(horizontalArrangement = Arrangement.SpaceBetween) { Column { for (item in myList) { Card { Text("Item: $item") items++ // Avoid! Side-effect of the column recomposing. } } } Text("Count: $items") } }
ในตัวอย่างนี้ ระบบจะแก้ไข items ทุกครั้งที่มีการจัดองค์ประกอบใหม่ ซึ่งอาจเป็นทุกเฟรมของภาพเคลื่อนไหว หรือเมื่อรายการได้รับการอัปเดต ไม่ว่าจะกรณีใดก็ตาม UI จะแสดงจำนวนที่ไม่ถูกต้อง ด้วยเหตุนี้ Compose จึงไม่รองรับการเขียนแบบนี้ การห้ามการเขียนดังกล่าวช่วยให้เฟรมเวิร์กเปลี่ยนเทรดเพื่อเรียกใช้ Lambda ที่ประกอบกันได้
ฟังก์ชันที่ประกอบกันได้สามารถเรียกใช้ตามลำดับใดก็ได้
เมื่อดูโค้ดของฟังก์ชันที่ประกอบกันได้ คุณอาจคิดว่าระบบจะเรียกใช้โค้ดตามลำดับที่ปรากฏ แต่เราไม่รับประกันว่าจะเป็นเช่นนั้น หากฟังก์ชันที่ประกอบกันได้มีการเรียกใช้ฟังก์ชันที่ประกอบกันได้อื่นๆ ฟังก์ชันเหล่านั้นอาจเรียกใช้ตามลำดับใดก็ได้ Compose มีตัวเลือกในการจดจำว่าองค์ประกอบ UI บางอย่างมีความสำคัญสูงกว่าองค์ประกอบอื่นๆ และวาดองค์ประกอบเหล่านั้นก่อน
ตัวอย่างเช่น สมมติว่าคุณมีโค้ดลักษณะนี้เพื่อวาดหน้าจอ 3 หน้าจอในเลย์เอาต์แท็บ
@Composable fun ButtonRow() { MyFancyNavigation { StartScreen() MiddleScreen() EndScreen() } }
การเรียกใช้ StartScreen, MiddleScreen และ EndScreen อาจเกิดขึ้นตามลำดับใดก็ได้ ซึ่งหมายความว่าคุณไม่สามารถให้ StartScreen() ตั้งค่าตัวแปรส่วนกลาง (ผลข้างเคียง) และให้ MiddleScreen() ใช้ประโยชน์จากการเปลี่ยนแปลงนั้นได้ แต่ฟังก์ชันแต่ละฟังก์ชันต้องมีข้อมูลครบถ้วนในตัวเอง
ดูข้อมูลเพิ่มเติม
ดูแหล่งข้อมูลเพิ่มเติมต่อไปนี้เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีคิดใน Compose และฟังก์ชันที่ประกอบกันได้
วิดีโอ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- Kotlin สำหรับ Jetpack Compose
- สถานะและ Jetpack Compose
- การแบ่งเลเยอร์สถาปัตยกรรมของ Jetpack Compose