การข้ามแบบเข้มงวดเป็นโหมดที่พร้อมใช้งานในคอมไพเลอร์ Compose เมื่อเปิดใช้ ตัวเลือกนี้จะเปลี่ยนลักษณะการทำงานของคอมไพเลอร์ใน 2 วิธีดังนี้
เปิดใช้โหมดการข้ามที่เข้มงวด
การข้ามแบบเข้มงวดจะเปิดใช้โดยค่าเริ่มต้นใน Kotlin 2.0.20
หากต้องการเปิดใช้การข้ามที่เข้มงวดสำหรับโมดูล Gradle ในรุ่นก่อน 2.0.20 ให้ใส่ตัวเลือกต่อไปนี้ในบล็อก composeCompiler ของการกำหนดค่า Gradle
android { ... }
composeCompiler {
enableStrongSkippingMode = true
}
ความสามารถในการข้ามที่ประกอบกันได้
โหมดการข้ามที่เข้มงวดจะผ่อนคลายกฎความเสถียรบางข้อที่คอมไพเลอร์ Compose มักใช้เมื่อพูดถึงการข้ามและฟังก์ชันที่ประกอบกันได้ โดยค่าเริ่มต้น คอมไพเลอร์ Compose จะทำเครื่องหมายฟังก์ชันที่ประกอบกันได้ว่าข้ามได้หากอาร์กิวเมนต์ทั้งหมดมีค่าที่เสถียร โหมดการข้ามแบบเข้มงวดจะเปลี่ยนลักษณะการทำงานนี้
เมื่อเปิดใช้การข้ามที่มีประสิทธิภาพ ฟังก์ชันที่ประกอบกันได้ซึ่งรีสตาร์ทได้ทั้งหมดจะข้ามได้ ซึ่งจะมีผลไม่ว่าพารามิเตอร์จะไม่เสถียรหรือไม่ก็ตาม ฟังก์ชันที่ประกอบกันได้ซึ่งรีสตาร์ทไม่ได้จะยังคงข้ามไม่ได้
กรณีที่ควรข้าม
ในการพิจารณาว่าจะข้าม Composable ในระหว่างการจัดองค์ประกอบใหม่หรือไม่ Compose จะเปรียบเทียบค่าของพารามิเตอร์แต่ละรายการกับค่าก่อนหน้า ประเภทของการเปรียบเทียบจะขึ้นอยู่กับความเสถียรของพารามิเตอร์
- พารามิเตอร์ที่ไม่เสถียรจะเปรียบเทียบโดยใช้ความเท่ากันของอินสแตนซ์ (
===) - ระบบจะเปรียบเทียบพารามิเตอร์ที่เสถียรโดยใช้ความเท่ากันของออบเจ็กต์ (
Object.equals())
หากพารามิเตอร์ทั้งหมดเป็นไปตามข้อกำหนดเหล่านี้ Compose จะข้าม Composable ในระหว่างการจัดองค์ประกอบใหม่
คุณอาจต้องการให้ Composable เลือกไม่ใช้การข้ามที่มีประสิทธิภาพ กล่าวคือ คุณอาจต้องการ Composable ที่รีสตาร์ทได้แต่ข้ามไม่ได้ ในกรณีนี้ ให้ใช้คำอธิบายประกอบ @NonSkippableComposable
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}
ใส่คำอธิบายประกอบคลาสว่าเสถียร
หากต้องการเปรียบเทียบออบเจ็กต์โดยใช้ความเท่ากันของออบเจ็กต์ (Object.equals()) แทนความเท่ากันของอินสแตนซ์ (===) ให้ใส่คำอธิบายประกอบคลาสที่ระบุด้วย @Stable หรือ @Immutable ต่อไป
โปรดคำนึงถึงข้อดีข้อเสียต่อไปนี้ก่อนเพิ่ม @Stable หรือ @Immutable
- คลาสที่มีพร็อพเพอร์ตี้ที่เสถียรในโมดูล Compose มีความเสถียรอยู่แล้ว: คลาสที่มีพร็อพเพอร์ตี้
valของประเภทที่เสถียรในโมดูลที่คอมไพล์ด้วยคอมไพเลอร์ Compose จะได้รับการอนุมานโดยอัตโนมัติว่าเสถียรและใช้.equals()โดยไม่ต้องใช้@Immutableหรือ@Stable - ใส่คำอธิบายประกอบเฉพาะคลาสที่มีการตรวจสอบ
.equals()ที่ใช้ทรัพยากรน้อย: เพิ่ม@Stableหรือ@Immutableเมื่อคอมไพเลอร์ไม่สามารถอนุมานความเสถียรได้ (เช่น คลาสจากโมดูลที่ไม่ใช่ Compose) และมีการจัดสรรอินสแตนซ์ใหม่ที่มีค่าเหมือนกันบ่อยครั้ง โดยที่การตรวจสอบ.equals()ของคลาสใช้ทรัพยากรน้อย - โปรดระมัดระวังเมื่อใส่คำอธิบายประกอบโมเดลด้วยคอลเล็กชัน: การเพิ่ม
@Stableหรือ@Immutableลงในโมเดลที่มีคอลเล็กชัน (หรือแทนที่Listด้วยImmutableList) จะทำให้ Compose เปรียบเทียบองค์ประกอบทุกรายการในคอลเล็กชันกับ.equals()ในการส่งผ่านการจัดองค์ประกอบใหม่แต่ละครั้ง สำหรับคอลเล็กชันหรือโมเดลขนาดใหญ่ที่ใช้ในเลย์เอาต์แบบ Lazy (LazyColumn,LazyRow,LazyGrid) การเปรียบเทียบทุกองค์ประกอบอาจช้ากว่าการใช้ความเท่ากันของอินสแตนซ์ (===) หรือการจัดองค์ประกอบใหม่โดยตรง
การจดจำ Lambda
โหมดการข้ามที่เข้มงวดยังช่วยให้จดจำ Lambda ภายใน Composable ได้มากขึ้นด้วย เมื่อเปิดใช้การข้ามแบบเข้มงวด ระบบจะจดจำ Lambda ทุกรายการภายในฟังก์ชันที่ประกอบกันได้โดยอัตโนมัติ
ตัวอย่าง
เพื่อให้เกิดการจดจำ Lambda ภายใน Composable เมื่อใช้การข้ามที่เข้มงวด คอมไพเลอร์จะรวม Lambda ของคุณด้วยการเรียก remember โดยจะใช้คีย์เป็นแคปเจอร์ของ Lambda
ลองพิจารณากรณีที่คุณมี Lambda ดังตัวอย่างต่อไปนี้
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = {
use(unstableObject)
use(stableObject)
}
}
เมื่อเปิดใช้การข้ามที่เข้มงวด คอมไพเลอร์จะจดจำ Lambda โดยรวมไว้ในการเรียก remember ดังนี้
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = remember(unstableObject, stableObject) {
{
use(unstableObject)
use(stableObject)
}
}
}
คีย์จะเป็นไปตามกฎการเปรียบเทียบเดียวกันกับฟังก์ชันที่ประกอบกันได้ รันไทม์จะเปรียบเทียบคีย์ที่ไม่เสถียรโดยใช้ความเท่ากันของอินสแตนซ์ โดยจะเปรียบเทียบคีย์ที่เสถียรโดยใช้ความเท่ากันของออบเจ็กต์
การจดจำและการจัดองค์ประกอบใหม่
การเพิ่มประสิทธิภาพนี้จะเพิ่มจำนวน Composable ที่รันไทม์ข้ามไปในระหว่างการจัดองค์ประกอบใหม่ได้อย่างมาก หากไม่มีการจดจำ รันไทม์มีแนวโน้มที่จะจัดสรรแลมบ์ดาใหม่ให้กับคอมโพสิเบิลที่ใช้พารามิเตอร์แลมบ์ดาระหว่างการจัดองค์ประกอบใหม่ ด้วยเหตุนี้ Lambda ใหม่จึงมีพารามิเตอร์ที่ไม่เท่ากับองค์ประกอบสุดท้าย ซึ่งจะส่งผลให้เกิดการจัดองค์ประกอบใหม่
หลีกเลี่ยงการใช้ Memoization
หากคุณมี Lambda ที่ไม่ต้องการจดจำ ให้ใช้คำอธิบายประกอบ @DontMemoize
val lambda = @DontMemoize {
...
}
ขนาด APK
เมื่อคอมไพล์แล้ว Composable ที่ข้ามได้จะส่งผลให้มีการสร้างโค้ดมากกว่า Composable ที่ข้ามไม่ได้ เมื่อเปิดใช้การข้ามแบบเข้มงวด คอมไพเลอร์จะทำเครื่องหมายคอมโพสิเบิลเกือบทั้งหมดว่าข้ามได้ และรวม Lambda ทั้งหมดไว้ใน remember{...} ด้วยเหตุนี้ การเปิดใช้โหมดการข้ามที่เข้มงวดจึงส่งผลต่อขนาด APK ของแอปพลิเคชันน้อยมาก
การเปิดใช้การข้ามที่มีประสิทธิภาพใน Now In Android เพิ่มขนาด APK ขึ้น 4 KB ความแตกต่างของขนาดขึ้นอยู่กับจำนวน Composable ที่ข้ามไม่ได้ก่อนหน้านี้ซึ่งมีอยู่ในแอปที่ระบุ แต่ควรมีขนาดค่อนข้างเล็ก