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

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

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

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

เลือกใช้การสร้างโค้ดแทนการสะท้อน

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

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

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

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

  • ใช้คลาสหรือเมธอดจากแพ็กเกจ 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 ทำงานได้ดีกับ การเพิ่มประสิทธิภาพแอป เนื่องจากส่วนใหญ่ใช้การสร้างโค้ดแทนการสะท้อน เมื่อใช้การสะท้อน ไลบรารีเหล่านี้จะให้กฎการเก็บรักษาขั้นต่ำเพื่อเก็บเฉพาะโค้ดที่จำเป็น
  • ไลบรารีการซีเรียลไลซ์มักใช้การสะท้อนเพื่อหลีกเลี่ยงโค้ดซ้ำๆ เมื่อสร้างอินสแตนซ์หรือซีเรียลไลซ์ออบเจ็กต์ ให้มองหาไลบรารีที่ใช้การสร้างโค้ดเพื่อ หลีกเลี่ยงปัญหาเหล่านี้ เช่น โดยใช้ Kotlin Serialization {:.external} หรือ Moshi with codegen แทนที่จะใช้วิธีการที่อิงตามการสะท้อน (เช่น Gson สำหรับ JSON)
  • หลีกเลี่ยงไลบรารีที่มีกฎการเก็บรักษาทั่วทั้งแพ็กเกจ หากเป็นไปได้ กฎการเก็บรักษาทั่วทั้งแพ็กเกจช่วยแก้ข้อผิดพลาดได้ แต่ควรกำหนดกฎการเก็บรักษาแบบกว้างให้ละเอียดขึ้นในภายหลังเพื่อเก็บเฉพาะโค้ดที่จำเป็น ดูข้อมูลเพิ่มเติมได้ที่ ดูที่ ใช้การเพิ่มประสิทธิภาพทีละน้อย
  • ก่อนเผยแพร่แอปที่ใช้ไลบรารีของบุคคลที่สาม ให้ใช้ R8 เครื่องมือวิเคราะห์การกำหนดค่า เพื่อตรวจสอบกฎการเก็บรักษาที่ไลบรารีนั้นมีให้ การตรวจสอบรายงานจะช่วยให้คุณยืนยันได้ว่ากฎการเก็บรักษาของไลบรารีกว้างเกินไปหรือไม่ ซึ่งอาจป้องกันไม่ให้ R8 ทำการเพิ่มประสิทธิภาพที่สำคัญในฐานของโค้ด การตรวจสอบนี้ช่วยให้มั่นใจว่าไลบรารีที่คุณเลือกสอดคล้องกับเป้าหมายด้านประสิทธิภาพของแอป และไม่ทำให้การกำหนดค่ามีขนาดใหญ่เกินความจำเป็น
  • ไลบรารีไม่ควรกำหนดให้คุณคัดลอกและวางกฎการเก็บรักษาจากเอกสารประกอบลงในไฟล์ในโปรเจ็กต์ โดยเฉพาะอย่างยิ่งกฎการเก็บรักษาทั่วทั้งแพ็กเกจ กฎเหล่านี้จะกลายเป็นภาระในการบำรุงรักษาสำหรับนักพัฒนาแอปในระยะยาว และยากต่อการเพิ่มประสิทธิภาพและเปลี่ยนแปลงเมื่อเวลาผ่านไป

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

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

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

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

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

// 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 ที่ใดก็ตาม ระบบจะเปลี่ยนชื่อฟิลด์หรือนำตัวสร้างที่ดูเหมือนไม่ได้ใช้ออก ซึ่งทำให้แอปขัดข้อง หากคุณใช้ไลบรารีอื่นๆ ในลักษณะที่คล้ายกัน คุณควรตรวจสอบว่าไลบรารีเหล่านั้นจะไม่รบกวนการเพิ่มประสิทธิภาพแอป และหากรบกวน ให้หลีกเลี่ยงการใช้

ใช้ @SerializedName กับ Gson เวอร์ชันที่ใหม่กว่า

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

import com.google.gson.annotations.SerializedName

class User(@SerializedName("name") val name: String)
class UserList(@SerializedName("users") val users: List<User>)

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

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