เลือกคลังอย่างชาญฉลาด

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

เคล็ดลับทั่วไปเมื่อเลือกไลบรารี

ใช้เคล็ดลับเหล่านี้เพื่อให้แน่ใจว่าไลบรารีของคุณเข้ากันได้กับการเพิ่มประสิทธิภาพแอป

ต้องการใช้ Codegen มากกว่าการสะท้อน

เลือกไลบรารีที่ใช้การสร้างโค้ด (codegen) แทนการสะท้อน ด้วย Codegen ตัวเพิ่มประสิทธิภาพจะระบุได้ง่ายขึ้นว่า โค้ดใดที่ใช้จริงในรันไทม์และโค้ดใดที่นำออกได้ การบอกว่าไลบรารีใช้ Codegen หรือ Reflection อาจเป็นเรื่องยาก แต่ก็มีสัญญาณบางอย่างที่ช่วยได้ โปรดดูเคล็ดลับเพื่อขอความช่วยเหลือ

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Codegen กับ Reflection ได้ที่การเพิ่มประสิทธิภาพสำหรับ ผู้เขียนไลบรารี

ตรวจสอบการใช้การสะท้อน (ขั้นสูง)

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

  • ใช้คลาสหรือเมธอดจากแพ็กเกจ kotlin.reflect หรือ java.lang.reflect
  • ใช้ฟังก์ชัน Class.forName หรือ classLoader.getClass
  • อ่านคำอธิบายประกอบที่รันไทม์ เช่น หากจัดเก็บค่าคำอธิบายประกอบ โดยใช้ val value = myClass.getAnnotation() หรือ val value = myMethod.getAnnotation() แล้วทำบางอย่างกับ value
  • เรียกใช้เมธอดโดยใช้ชื่อเมธอดเป็นสตริง ดังตัวอย่างต่อไปนี้

    // Calls the private `processData` API with reflection
    myObject.javaClass.getMethod("processData", DataType::class.java)
    ?.invoke(myObject, data)
    

ตรวจสอบปัญหาการเพิ่มประสิทธิภาพ

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

  • ไลบรารี AndroidX และไลบรารีต่างๆ เช่น Hilt ทำงานร่วมกับการเพิ่มประสิทธิภาพแอปได้ดี เนื่องจากส่วนใหญ่ใช้ Codegen แทนการสะท้อน เมื่อใช้การสะท้อน ระบบจะระบุกฎการเก็บรักษาน้อยที่สุดเพื่อเก็บเฉพาะโค้ดที่จำเป็น
  • ไลบรารีการซีเรียลไลซ์มักใช้การสะท้อนเพื่อหลีกเลี่ยงโค้ดสำเร็จรูป เมื่อสร้างอินสแตนซ์หรือซีเรียลไลซ์ออบเจ็กต์ แทนที่จะใช้วิธีการที่อิงตามการสะท้อน (เช่น Gson สำหรับ JSON) ให้มองหาไลบรารีที่ใช้ Codegen เพื่อ หลีกเลี่ยงปัญหาเหล่านี้ เช่น การใช้ Kotlin Serialization หรือ Moshi กับ Codegen
  • หากเป็นไปได้ ให้หลีกเลี่ยงไลบรารีที่มีกฎการเก็บรักษาทั้งแพ็กเกจ กฎการเก็บรักษาระดับแพ็กเกจช่วยแก้ไขข้อผิดพลาดได้ แต่ควรปรับแต่งกฎการเก็บรักษาแบบกว้างในท้ายที่สุดเพื่อเก็บเฉพาะโค้ดที่จำเป็น ดูข้อมูลเพิ่มเติมได้ที่ใช้การเพิ่มประสิทธิภาพทีละขั้น
  • ไลบรารีไม่ควรบังคับให้คุณคัดลอกและวางกฎการเก็บรักษาจากเอกสารประกอบลงในไฟล์ในโปรเจ็กต์ โดยเฉพาะกฎการเก็บรักษาระดับแพ็กเกจ กฎเหล่านี้กลายเป็นภาระในการบำรุงรักษาสำหรับนักพัฒนาแอปในระยะยาว และยากต่อการเพิ่มประสิทธิภาพและเปลี่ยนแปลงเมื่อเวลาผ่านไป

เปิดใช้การเพิ่มประสิทธิภาพหลังจากเพิ่มคลังใหม่

เมื่อเพิ่มไลบรารีใหม่ ให้เปิดใช้การเพิ่มประสิทธิภาพในภายหลังและตรวจสอบว่ามีข้อผิดพลาดหรือไม่ หากมีข้อผิดพลาด ให้มองหาทางเลือกอื่นสำหรับไลบรารีนั้นหรือเขียน กฎการเก็บ หากไลบรารีไม่รองรับการเพิ่มประสิทธิภาพ ให้รายงานข้อบกพร่องของไลบรารีนั้น

กรองกฎการเก็บรักษาที่ไม่ดีออก (ขั้นสูง)

กฎการเก็บรักษาเป็นส่วนเสริม ซึ่งหมายความว่ากฎบางอย่างที่ทรัพยากร Dependency ของไลบรารี รวมอยู่ด้วยจะนำออกไม่ได้ และอาจส่งผลต่อการคอมไพล์ส่วนอื่นๆ ของ แอป เช่น หากไลบรารีมีกฎที่ปิดใช้การเพิ่มประสิทธิภาพโค้ด กฎดังกล่าวจะปิดใช้การเพิ่มประสิทธิภาพทั้งโปรเจ็กต์

คุณควรหลีกเลี่ยงไลบรารีที่มีกฎ Keep ที่เก็บโค้ดที่ควรนำออก แต่หากจำเป็นต้องใช้ คุณสามารถกรองกฎออกได้ตามที่แสดงในโค้ดต่อไปนี้

// If you're using AGP 8.4 and higher
buildTypes {
    release {
        optimization.keepRules {
          it.ignoreFrom("com.somelibrary:somelibrary")
        }
    }
}

// If you're using AGP 7.3-8.3
buildTypes {
    release {
        optimization.keepRules {
          it.ignoreExternalDependencies("com.somelibrary:somelibrary")
        }
    }
}

กรณีศึกษา: เหตุใด Gson จึงไม่ทำงานเมื่อมีการเพิ่มประสิทธิภาพ

Gson เป็นไลบรารีการซีเรียลไลซ์ที่มักทำให้เกิดปัญหาเกี่ยวกับการเพิ่มประสิทธิภาพแอป เนื่องจากใช้การสะท้อนอย่างมาก ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ Gson โดยทั่วไป ซึ่งอาจทำให้เกิดข้อขัดข้องในรันไทม์ได้ง่าย โปรดทราบว่าเมื่อคุณ ใช้ Gson เพื่อรับรายการออบเจ็กต์ User คุณจะไม่เรียกใช้ตัวสร้างหรือส่ง Factory ไปยังฟังก์ชัน fromJson() การสร้างหรือใช้คลาสที่แอปกำหนด โดยไม่มีสิ่งต่อไปนี้เป็นสัญญาณว่าไลบรารีอาจใช้ การสะท้อนแบบเปิด

  • คลาสแอปที่ใช้ไลบรารี หรืออินเทอร์เฟซหรือคลาสมาตรฐาน
  • ปลั๊กอินการสร้างโค้ด เช่น KSP
class User(val name: String)
class UserList(val users: List<User>)

// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()

หากต้องการทำความเข้าใจวิธีที่ R8 ทำงานกับ Gson โปรดดูกฎสำหรับผู้ใช้ Gson เมื่อ R8 วิเคราะห์โค้ดนี้และไม่พบว่ามีการสร้างอินสแตนซ์ของ UserList หรือ User ที่ใดก็ตาม R8 จะเปลี่ยนชื่อฟิลด์หรือนำตัวสร้างที่ดูเหมือนไม่ได้ใช้ ออก ซึ่งจะทำให้แอปขัดข้อง หากคุณใช้ไลบรารีอื่นๆ ในลักษณะที่คล้ายกัน คุณควรตรวจสอบว่าไลบรารีเหล่านั้นจะไม่รบกวนการเพิ่มประสิทธิภาพแอป และหาก รบกวน ก็ควรหลีกเลี่ยง

หากต้องการกำหนดคลาสในลักษณะที่เข้ากันได้กับกฎสำหรับผู้ใช้ของ Gson ให้ใช้ข้อมูลโค้ดต่อไปนี้เป็นข้อมูลอ้างอิง

class User(@com.google.gson.annotations.SerializedName("name") val name: String)
class UserList(@com.google.gson.annotations.SerializedName("users") val users: List<User>)

โปรดทราบว่า Room, Hilt และ Moshi ที่มี Codegen จะสร้างประเภทที่แอปกำหนด แต่ใช้ Codegen เพื่อหลีกเลี่ยงการใช้การสะท้อน