ทำตามแนวทางปฏิบัติแนะนำ

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

รูปแบบที่ดีในกฎการเก็บ

กฎการเก็บที่กำหนดไว้อย่างดีจะมีความเฉพาะเจาะจงมากที่สุดเท่าที่จะเป็นไปได้และเป็นไปตามรูปแบบต่อไปนี้

  • สำหรับการระบุคลาส ให้ระบุคลาสเฉพาะ คลาสฐาน หรือ คลาสที่มีคำอธิบายประกอบเสมอหากเป็นไปได้ ดังตัวอย่างต่อไปนี้

    -keepclassmembers class com.example.MyClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers ** extends com.example.MyBaseClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers @com.example.MyAnnotation class ** {
      void someSpecificMethod();
    }
    
  • ใช้คำอธิบายประกอบในซอร์สโค้ดทุกครั้งที่เป็นไปได้ แล้วกำหนดเป้าหมายคำอธิบายประกอบเหล่านั้น โดยตรงในกฎการเก็บ ซึ่งจะสร้างลิงก์ที่ชัดเจนและเจาะจง ระหว่างโค้ดกับกฎที่รักษาโค้ดนั้นไว้ ทำให้การกำหนดค่า มีความเสถียรมากขึ้น เข้าใจง่ายขึ้น และมีโอกาสน้อยที่จะเกิดข้อผิดพลาดเมื่อมีการเปลี่ยนแปลงโค้ด

    เช่น ข้อมูลโค้ดต่อไปนี้แสดงวิธีเก็บคลาส MyClass รวมถึงคลาสอื่นๆ ที่มีคำอธิบายประกอบด้วย @com.example.DisplayComponent

    // In the source code
    @com.example.DisplayComponent
    class MyClass { /* ... */ }
    
    // In the keep rules
    -keep @com.example.DisplayComponent class * {*;}
    

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

  • ควรประกาศข้อกำหนดของสมาชิกทุกครั้งที่เป็นไปได้ และอ้างอิงเฉพาะส่วนของคลาสที่ต้องเก็บไว้เพื่อให้แอปทำงานได้ ขอแนะนำว่าไม่ควรใช้กฎกับทั้งชั้นเรียนโดยการกำหนด ขอบเขตสมาชิกที่ไม่บังคับเป็น { *; } เว้นแต่จะจำเป็นอย่างยิ่ง

    -keepclassmembers com.example.MyClass {
      void someSpecificMethod();
      void @com.example.MyAnnotation *;
    }
    
  • หากใช้repackageclasses ตัวเลือกส่วนกลาง ให้หลีกเลี่ยงการระบุชื่อแพ็กเกจที่ไม่บังคับ ซึ่งส่งผลให้ไฟล์ DEX มีขนาดเล็กลงเนื่องจากระบบจะละเว้น คำนำหน้าแพ็กเกจในชื่อคลาสที่แพ็กเกจใหม่

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

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

-keepclassmembers class com.example.pkg.** { *; }

สิ่งที่ควรหลีกเลี่ยง

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

  • อย่าใช้กฎการเก็บระดับแพ็กเกจ เช่น -keep class com.example.pkg.** { *; } ระยะยาว ซึ่งใช้ชั่วคราวเพื่อหลีกเลี่ยงปัญหาเมื่อ กำหนดค่า R8 ได้ ดูข้อมูลเพิ่มเติมได้ที่จำกัดขอบเขตการเพิ่มประสิทธิภาพ โดยทั่วไปแล้ว ให้ระมัดระวังการใช้ไวลด์การ์ด และตรวจสอบว่าคุณเก็บเฉพาะโค้ดที่จำเป็นเท่านั้น
  • หากเป็นไปได้ ให้หลีกเลี่ยงไลบรารีที่แนะนำให้คุณคัดลอกและวางกฎการเก็บรักษา เมื่อใช้ไลบรารี โดยเฉพาะกฎการเก็บรักษาระดับแพ็กเกจ ไลบรารีที่ออกแบบมาเพื่อ ทำงานได้ดีใน Android ควรหลีกเลี่ยงการใช้การสะท้อนเมื่อเป็นไปได้ และฝังกฎการเก็บรักษาสำหรับผู้ใช้เมื่อจำเป็น
  • หลีกเลี่ยงการใช้ตัวดำเนินการผกผัน ! ในกฎการเก็บรักษา เนื่องจากคุณอาจใช้กฎกับคลาสเกือบทุกคลาสในแอปพลิเคชันโดยไม่ตั้งใจ

หากทำตามกฎเหล่านี้ไม่ได้ คุณอาจใช้การสะท้อนแบบปลายเปิดมากเกินไป และควรหลีกเลี่ยงการสะท้อนหรือหลีกเลี่ยงการใช้ไลบรารีที่ใช้การสะท้อน (ดูกรณีศึกษาของ Gson)