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