เมื่อเจอชั้นเรียนที่ไม่เสถียรซึ่งทำให้ประสิทธิภาพ คุณควรทำให้เวอร์ชันเสถียร เอกสารนี้ได้สรุปเทคนิคต่างๆ ที่คุณ ที่สามารถทำได้
เปิดใช้การข้ามอย่างเข้มงวด
คุณควรลองเปิดใช้โหมดการข้ามขั้นสูงก่อน โหมดการข้ามแบบเข้มงวด ช่วยให้ข้าม Composable ที่มีพารามิเตอร์ที่ไม่เสถียรได้ และเป็นวิธีที่ง่ายที่สุด เพื่อแก้ไขปัญหาด้านประสิทธิภาพที่เกิดจากความเสถียร
ดูข้อมูลเพิ่มเติมที่การข้ามอย่างแรง
ทำให้ชั้นเรียนดำเนินไปไม่ได้
นอกจากนี้ คุณยังสามารถพยายามทำให้ชั้นเรียนที่ไม่เสถียรนั้นเปลี่ยนแปลงไม่ได้เลยก็ได้
- เปลี่ยนแปลงไม่ได้: ระบุประเภทที่ค่าของพร็อพเพอร์ตี้ใดๆ ต้องไม่มี
เปลี่ยนหลังสร้างอินสแตนซ์ของประเภทนั้นๆ และเมธอดทั้งหมด
มีความโปร่งใสในการอ้างอิง
- ตรวจสอบว่าพร็อพเพอร์ตี้ทั้งหมดของชั้นเรียนเป็นทั้ง
val
ไม่ใช่var
และเปลี่ยนแปลงไม่ได้ - ประเภทพื้นฐาน เช่น
String, Int
และFloat
จะเปลี่ยนแปลงไม่ได้เสมอ - หากเป็นไปไม่ได้ คุณต้องใช้สถานะ Compose สำหรับ พร็อพเพอร์ตี้ที่เปลี่ยนแปลงได้
- ตรวจสอบว่าพร็อพเพอร์ตี้ทั้งหมดของชั้นเรียนเป็นทั้ง
- เสถียร: ระบุประเภทที่เปลี่ยนแปลงได้ รันไทม์ของ Compose จะไม่ ตระหนักถึงคุณสมบัติหรือวิธีการสาธารณะประเภทใดและเมื่อใด พฤติกรรมจะให้ผลลัพธ์ที่แตกต่างจากการเรียกใช้ก่อนหน้า
คอลเล็กชันที่เปลี่ยนแปลงไม่ได้
สาเหตุทั่วไปที่ Compose ถือว่าชั้นเรียนไม่เสถียรคือคอลเล็กชัน ตามที่ระบุไว้
ในหน้าวิเคราะห์ปัญหาความเสถียร
ก็ไม่สามารถแน่ใจได้เต็มร้อยว่าคอลเล็กชัน เช่น List, Map
และ Set
จะเปลี่ยนแปลงไม่ได้จริงๆ จึงทำเครื่องหมายว่าไม่เสถียร
หากต้องการแก้ไขปัญหานี้ คุณสามารถใช้คอลเล็กชันที่เปลี่ยนแปลงไม่ได้ คอมไพเลอร์ Compose รวมการรองรับคอลเล็กชันที่เปลี่ยนแปลงไม่ได้ของ Kotlinx เหล่านี้ คอลเล็กชันต่างๆ รับประกันว่าจะเปลี่ยนแปลงไม่ได้ และคอมไพเลอร์ของ Compose จะจัดการกับคอลเล็กชันเหล่านี้ เช่นนี้ ไลบรารีนี้ยังคงอยู่ในเวอร์ชันอัลฟ่า ดังนั้นโปรดรอการเปลี่ยนแปลง API ที่อาจเกิดขึ้น
ลองพิจารณาคลาสที่ไม่เสถียรนี้อีกครั้งจากวิเคราะห์ความเสถียร ของ Google ด้วยตนเอง
unstable class Snack {
…
unstable val tags: Set<String>
…
}
คุณสามารถทำให้ tags
เสถียรโดยใช้คอลเล็กชันที่เปลี่ยนแปลงไม่ได้ เปลี่ยนชั้นเรียน
ประเภทของ tags
เป็น ImmutableSet<String>
:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
หลังจากทำเช่นนั้น พารามิเตอร์ของคลาสทั้งหมดจะเปลี่ยนแปลงไม่ได้และฟังก์ชัน Compose คอมไพเลอร์จะทำเครื่องหมายคลาสว่าเสถียร
ใส่คำอธิบายประกอบด้วย Stable
หรือ Immutable
เส้นทางที่เป็นไปได้ในการแก้ปัญหาความเสถียรคือการใส่คำอธิบายประกอบชั้นเรียนที่ไม่เสถียร
ด้วย @Stable
หรือ @Immutable
การใส่คำอธิบายประกอบชั้นเรียนจะเป็นการลบล้างสิ่งที่คอมไพเลอร์จะ
อนุมานเกี่ยวกับชั้นเรียนของคุณ ซึ่งคล้ายกับ
!!
โอเปอเรเตอร์ใน Kotlin ควรเป็น
โปรดระมัดระวังเกี่ยวกับวิธีที่คุณใช้คำอธิบายประกอบเหล่านี้ การลบล้างการทำงานของคอมไพเลอร์
อาจทำให้เกิดข้อบกพร่องที่ไม่คาดคิด เช่น Composable ไม่ปรับแต่งเมื่อ
ที่คุณคาดหวัง
หากทำให้ชั้นเรียนของคุณเสถียรโดยไม่ต้องมีคำอธิบายประกอบ คุณควร จงพยายามทำให้มีเสถียรภาพ
ข้อมูลโค้ดต่อไปนี้ให้ตัวอย่างเล็กน้อยของคลาสข้อมูลที่มีคำอธิบายประกอบเป็น เปลี่ยนแปลงไม่ได้:
@Immutable
data class Snack(
…
)
ไม่ว่าคุณจะใช้คำอธิบายประกอบ @Immutable
หรือ @Stable
คอมไพเลอร์ Compose
ทำเครื่องหมายคลาส Snack
ว่าเสถียร
ชั้นเรียนที่มีคำอธิบายประกอบในคอลเล็กชัน
พิจารณา Composable ที่มีพารามิเตอร์ประเภท List<Snack>
:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
แม้ว่าคุณจะใส่คำอธิบายประกอบ Snack
ด้วย @Immutable
แล้ว คอมไพเลอร์ Compose จะยังคงทำเครื่องหมาย
พารามิเตอร์ snacks
ใน HighlightedSnacks
ไม่เสถียร
พารามิเตอร์พบปัญหาเดียวกันกับคลาสเมื่อพูดถึงประเภทคอลเล็กชัน
คอมไพเลอร์ Compose จะทำเครื่องหมายพารามิเตอร์ประเภท List
ว่าไม่เสถียรเสมอ แม้ว่า
เมื่อเป็นคอลเล็กชันของประเภทคงที่
คุณไม่สามารถทำเครื่องหมายพารามิเตอร์แต่ละรายการว่าเสถียร และไม่สามารถใส่คำอธิบายประกอบ Composable เพื่อให้ข้ามได้เสมอ มีเส้นทางไปข้างหน้าหลายเส้นทาง
คุณสามารถหลีกเลี่ยงปัญหาคอลเล็กชันที่ไม่เสถียรได้หลายวิธี ส่วนย่อยต่อไปนี้จะแสดงวิธีการที่แตกต่างกัน
ไฟล์การกำหนดค่า
หากคุณยินดีจะปฏิบัติตามสัญญาความเสถียรในฐานของโค้ด
ก็เลือกใช้เพื่อพิจารณาให้คอลเล็กชัน Kotlin เสถียรได้โดยการเพิ่ม
kotlin.collections.*
ไปยัง
ไฟล์การกำหนดค่าความเสถียร
คอลเล็กชันที่เปลี่ยนแปลงไม่ได้
เพื่อความปลอดภัยของเวลาคอมไพล์สำหรับการเปลี่ยนแปลงไม่ได้ คุณสามารถ
ใช้คอลเล็กชันที่เปลี่ยนแปลงไม่ได้ของ kotlinx แทน List
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
หากใช้คอลเล็กชันที่เปลี่ยนแปลงไม่ได้ คุณก็สร้างคอลเล็กชันของตัวเองได้ โดยดำเนินการดังนี้
รวม List
ในคลาสแบบคงที่ที่มีคำอธิบายประกอบ Wrapper ทั่วไปมีแนวโน้มที่จะ
ตัวเลือกนี้ดีที่สุดโดยขึ้นอยู่กับความต้องการของคุณ
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
จากนั้นคุณสามารถใช้พารามิเตอร์นี้เป็นประเภทของพารามิเตอร์ใน Composable
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
โซลูชัน
หลังจากใช้ทั้งสองวิธี คอมไพเลอร์ Compose จะทำเครื่องหมาย
HighlightedSnacks
เขียนได้ทั้ง skippable
และ restartable
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
stable snacks: ImmutableList<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
ระหว่างการจัดองค์ประกอบใหม่ Compose สามารถข้าม HighlightedSnacks
ได้แล้ว หากไม่มี
มีการเปลี่ยนแปลง
ไฟล์การกำหนดค่าความเสถียร
เริ่มต้นด้วย Compose Compiler 1.5.5 ซึ่งเป็นไฟล์การกำหนดค่าของคลาส
ควรพิจารณาว่าสามารถระบุ "เวอร์ชันเสถียร" ได้ในเวลาคอมไพล์ ซึ่งช่วยให้สามารถพิจารณา
ชั้นเรียนที่คุณไม่ได้ควบคุม เช่น ชั้นเรียนห้องสมุดมาตรฐาน
เช่น LocalDateTime
เสถียร
ไฟล์การกำหนดค่าคือไฟล์ข้อความธรรมดาที่มี 1 คลาสต่อแถว ความคิดเห็น สามารถใช้ไวลด์การ์ดเดี่ยวและไวลด์การ์ดคู่ ตัวอย่างการกำหนดค่ามีดังต่อไปนี้
// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>
หากต้องการเปิดใช้งานฟีเจอร์นี้ ให้ส่งเส้นทางของไฟล์การกำหนดค่าไปยังส่วน "เขียน" คอมไพเลอร์
ดึงดูด
kotlinOptions {
freeCompilerArgs += [
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
project.absolutePath + "/compose_compiler_config.conf"
]
}
Kotlin
kotlinOptions {
freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
"${project.absolutePath}/compose_compiler_config.conf"
)
}
เมื่อคอมไพเลอร์ Compose ทำงานอยู่ในแต่ละโมดูลในโปรเจ็กต์ของคุณแยกกัน คุณจึงสามารถดำเนินการต่อไปนี้ได้ จัดเตรียมการกำหนดค่าที่แตกต่างกันให้กับโมดูลต่างๆ หากจำเป็น อีกวิธีหนึ่งคือ ที่ระดับรากของโปรเจ็กต์และส่งเส้นทางนั้นไปยัง
หลายโมดูล
ปัญหาทั่วไปอีกอย่างที่เกี่ยวข้องกับสถาปัตยกรรมหลายโมดูล คอมไพเลอร์ Compose สามารถอนุมานได้เฉพาะว่าคลาสมีความเสถียรหรือไม่ก็ต่อเมื่อมีประเภทที่ไม่ใช่พื้นฐานทั้งหมดที่ มีการทำเครื่องหมายไว้อย่างชัดแจ้งว่า "เสถียร" หรือ "อยู่ในโมดูล" ก็สร้างขึ้นด้วยคอมไพเลอร์ Compose เช่นกัน
หากชั้นข้อมูลอยู่ในโมดูลที่แยกต่างหากในเลเยอร์ UI ซึ่งก็คือ การดำเนินการที่แนะนำ นี่อาจเป็นปัญหาที่คุณพบ
โซลูชัน
ในการแก้ไขปัญหานี้ คุณสามารถใช้วิธีใดวิธีหนึ่งต่อไปนี้
- เพิ่มคลาสลงในไฟล์การกำหนดค่าคอมไพเลอร์
- เปิดใช้งานคอมไพเลอร์ Compose ในโมดูลชั้นข้อมูลหรือแท็กชั้นเรียนของคุณ
กับ
@Stable
หรือ@Immutable
ตามความเหมาะสม- ซึ่งรวมถึงการเพิ่มทรัพยากร Dependency ของ Compose ลงในชั้นข้อมูลของคุณ อย่างไรก็ตาม
นี่เป็นเพียงการพึ่งพารันไทม์ Compose ไม่ใช่สำหรับ
Compose-UI
- ซึ่งรวมถึงการเพิ่มทรัพยากร Dependency ของ Compose ลงในชั้นข้อมูลของคุณ อย่างไรก็ตาม
นี่เป็นเพียงการพึ่งพารันไทม์ Compose ไม่ใช่สำหรับ
- ภายในโมดูล UI ให้รวมคลาสชั้นข้อมูลไว้ใน Wrapper สำหรับ UI โดยเฉพาะ ใหม่
ปัญหาเดียวกันนี้ยังเกิดขึ้นเมื่อใช้ไลบรารีภายนอกหากไม่ใช้ไลบรารี เขียนคอมไพเลอร์
Composable บางรายการไม่ควรข้ามได้
เวลาที่แก้ไขปัญหาเกี่ยวกับความเสถียร คุณไม่ควรพยายามทำให้ ข้ามได้ การพยายามทำเช่นนั้น อาจนำไปสู่การเพิ่มประสิทธิภาพล่วงหน้า ที่นำมาซึ่งปัญหาต่างๆ มากกว่าการแก้ไข
มีหลายกรณีที่การข้ามได้ไม่ได้เกิดประโยชน์อย่างแท้จริง และอาจทำให้โค้ดจัดการได้ยาก เช่น
- Composable ที่ไม่ได้เขียนใหม่บ่อยครั้งหรือไม่ได้เลย
- Composable ที่ใช้เรียก Composable ที่ข้ามได้
- Composable ที่มีพารามิเตอร์จำนวนมากที่มีค่าเท่ากับราคาแพง การนำไปใช้งานจริง ในกรณีนี้ ค่าใช้จ่ายในการตรวจสอบว่าพารามิเตอร์ อาจมีน้ำหนักมากกว่าต้นทุนในการจัดองค์ประกอบใหม่ที่มีต้นทุนต่ำ
เมื่อ Composable เป็นแบบข้ามได้ ระบบจะเพิ่มค่าใช้จ่ายในการดำเนินการเล็กน้อยซึ่งอาจไม่คุ้มกับ ได้ คุณยังใส่คำอธิบายประกอบ Composable ให้ไม่สามารถรีสตาร์ทได้ได้ในกรณีต่างๆ โดยที่คุณเห็นว่าการเริ่มต้นใหม่นั้นมีค่าใช้จ่ายมากกว่าที่คุ้มค่า