โหมดการข้ามแบบเข้มงวด

การข้ามอย่างเข้มงวดเป็นโหมดที่มีอยู่ในคอมไพเลอร์ Compose เมื่อเปิดใช้ ตัวเลือกนี้จะเปลี่ยนลักษณะการทํางานของคอมไพเลอร์ 2 วิธีดังนี้

  • คอมโพสิเบิลที่มีพารามิเตอร์ที่ไม่เสถียรจะข้ามได้
  • ระบบจะจดจำ Lambda ที่มีการเก็บที่ไม่เสถียร

เปิดใช้โหมดข้ามอย่างมีประสิทธิภาพ

การข้ามที่เข้มงวดจะเปิดใช้โดยค่าเริ่มต้นใน Kotlin 2.0.20

หากต้องการเปิดใช้การข้ามอย่างเข้มงวดสำหรับโมดูล Gradle ในรุ่นก่อน 2.0.20 ให้ใส่ตัวเลือกต่อไปนี้ในบล็อก composeCompiler ของการกําหนดค่า Gradle

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

ความสามารถในการข้ามที่คอมโพสได้

โหมดการข้ามที่เข้มงวดจะผ่อนปรนกฎความเสถียรบางอย่างที่คอมไพเลอร์ Compose มักใช้กับการข้ามและฟังก์ชันคอมโพสิเบิล โดยค่าเริ่มต้น คอมไพเลอร์ Compose จะทําเครื่องหมายฟังก์ชันคอมโพสิเบิลว่าข้ามได้หากอาร์กิวเมนต์ทั้งหมดมีค่าที่แน่นอน โหมดข้ามวิดีโออย่างละเอียดจะเปลี่ยนการตั้งค่านี้

เมื่อเปิดใช้การข้ามอย่างเข้มงวด ฟังก์ชันคอมโพสิเบิลที่รีสตาร์ทได้ทั้งหมดจะข้ามได้ ซึ่งมีผลไม่ว่าจะมีพารามิเตอร์ที่ไม่เสถียรหรือไม่ก็ตาม ฟังก์ชันที่ประกอบกันได้ซึ่งไม่สามารถเริ่มใหม่ได้จะยังคงข้ามไม่ได้

กรณีที่ควรข้าม

Compose จะเปรียบเทียบค่าของพารามิเตอร์แต่ละรายการกับค่าก่อนหน้าเพื่อพิจารณาว่าจะข้ามคอมโพสิเบิลระหว่างการจัดองค์ประกอบใหม่หรือไม่ ประเภทการเปรียบเทียบจะขึ้นอยู่กับความเสถียรของพารามิเตอร์

  • ระบบจะเปรียบเทียบพารามิเตอร์ที่ไม่เสถียรโดยใช้ความเท่าเทียมของอินสแตนซ์ (===)
  • ระบบจะเปรียบเทียบพารามิเตอร์ที่เสถียรโดยใช้การเปรียบเทียบความเท่าเทียมของออบเจ็กต์ (Object.equals())

หากพารามิเตอร์ทั้งหมดเป็นไปตามข้อกำหนดเหล่านี้ คอมโพสิชันจะข้ามคอมโพสิเบิลในระหว่างการจัดองค์ประกอบใหม่

คุณอาจต้องการคอมโพสิเบิลเพื่อเลือกไม่ใช้การข้ามโฆษณาอย่างหนัก กล่าวคือ คุณอาจต้องการคอมโพสิเบิลที่รีสตาร์ทได้แต่ข้ามไม่ได้ ในกรณีนี้ ให้ใช้คำอธิบายประกอบ @NonSkippableComposable

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

กำกับเนื้อหาว่าเวอร์ชันเสถียร

หากต้องการให้ออบเจ็กต์ใช้ความเท่าเทียมกันของออบเจ็กต์แทนความเท่าเทียมกันของอินสแตนซ์ ให้กำกับเนื้อหาของคลาสนั้นด้วย @Stable ตัวอย่างกรณีที่คุณอาจต้องทำเช่นนี้คือเมื่อสังเกตรายการวัตถุทั้งหมด แหล่งข้อมูลอย่าง Room จะจัดสรรวัตถุใหม่สำหรับทุกรายการในรายการทุกครั้งที่มีการเปลี่ยนแปลงรายการใดรายการหนึ่ง

การช่วยจําของ Lambda

โหมดการข้ามที่เข้มงวดยังช่วยให้มีการคงค่า Lambda เพิ่มเติมภายในคอมโพสิเบิล เมื่อเปิดใช้การข้ามอย่างเข้มงวด ระบบจะจดจำ Lambda ทั้งหมดภายในฟังก์ชันคอมโพสิเบิลโดยอัตโนมัติ

ตัวอย่าง

หากต้องการใช้การจําค่าของ Lambda ภายในคอมโพสิเบิลเมื่อใช้การข้ามที่เข้มงวด คอมไพเลอร์จะรวม Lambda ของคุณด้วยการเรียกใช้ remember โดยมีการจับคู่กับข้อมูลการจับภาพของ Lambda

ลองพิจารณากรณีที่คุณมี 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)
        }
    }
}

โดยคีย์จะเป็นไปตามกฎการเปรียบเทียบเดียวกับฟังก์ชันคอมโพสิเบิล รันไทม์จะเปรียบเทียบคีย์ที่ไม่เสถียรโดยใช้ความเท่าเทียมของอินสแตนซ์ โดยจะเปรียบเทียบคีย์ที่เสถียรโดยใช้ความเท่าเทียมของออบเจ็กต์

การจําและการจัดองค์ประกอบใหม่

การเพิ่มประสิทธิภาพนี้ช่วยเพิ่มจํานวนคอมโพสิเบิลที่รันไทม์ข้ามไปในระหว่างการจัดองค์ประกอบใหม่ได้อย่างมาก หากไม่มีการช่วยจํา รันไทม์มีแนวโน้มที่จะจัดสรร Lambda ใหม่ให้กับคอมโพสิเบิลที่ใช้พารามิเตอร์ Lambda ในระหว่างการจัดเรียงใหม่มากกว่า ด้วยเหตุนี้ แลมดาใหม่จึงมีพารามิเตอร์ที่ไม่เท่ากับการคอมโพสิชันล่าสุด ซึ่งส่งผลให้มีการปรับองค์ประกอบใหม่

หลีกเลี่ยงการจํา

หากมี Lambda ที่ไม่ต้องการให้จัดเก็บข้อมูลเมโม ให้ใช้@DontMemoize คำอธิบายประกอบ

val lambda = @DontMemoize {
    ...
}

ขนาด APK

เมื่อคอมไพล์ Composable ที่ข้ามได้จะส่งผลให้โค้ดที่สร้างขึ้นมีจำนวนมากกว่า Composable ที่ข้ามไม่ได้ เมื่อเปิดใช้การข้ามแบบเข้มงวดแล้ว คอมไพเลอร์จะทําเครื่องหมายคอมโพสิเบิลเกือบทั้งหมดเป็นแบบข้ามได้ และรวม Lambda ทั้งหมดไว้ใน remember{...} ด้วยเหตุนี้ การเปิดใช้โหมดข้ามอย่างเข้มงวดจึงส่งผลต่อขนาด APK ของแอปพลิเคชันเพียงเล็กน้อย

การเปิดใช้การข้ามแบบบังคับในตอนนี้ใน Android ทำให้ขนาด APK เพิ่มขึ้น 4KB ความแตกต่างของขนาดจะขึ้นอยู่กับจํานวนคอมโพสิเบิลที่ข้ามไม่ได้ก่อนหน้านี้ซึ่งอยู่ในแอปนั้นๆ แต่ควรมีขนาดเล็ก