שימוש בשיטות המומלצות

כשעובדים עם כללי שמירה, חשוב להגיע לרמת ספציפיות מתאימה כדי ליהנות מהיתרונות של הכללים בלי לשנות את אופן הפעולה של האפליקציה. בקטעים הבאים מוסבר על דפוסים מומלצים ועל דברים שכדאי להימנע מהם בכללי שמירה.

דפוסים טובים בכללי השמירה

כללי שמירה מוגדרים היטב הם ספציפיים ככל האפשר:

  • במפרט הכיתה, תמיד מציינים כיתה ספציפית, כיתה בסיסית או כיתה עם הערות, אם אפשר, כמו בדוגמאות הבאות:

    -keepclassmembers class com.example.MyClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers ** extends com.example.MyBaseClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers @com.example.MyAnnotation class ** {
      void someSpecificMethod();
    }
    
  • בכל הזדמנות, כדאי להשתמש בהערות בקוד המקור (כמו @Keep הערה) ואז לטרגט את ההערות האלה ישירות בכללי השמירה. כך נוצר קישור ברור ומפורש בין הקוד לבין הכללים ששומרים עליו, וההגדרה הופכת לחזקה יותר, קלה יותר להבנה ופחות רגישה לשגיאות כשמבצעים שינויים בקוד.

    לדוגמה, ספריות כמו androidx.annotation משתמשות בדפוס הזה:

    // In your source code
    @Keep
    class MyDataClass { /* ... */ }
    
    // In your R8 rules
    -keep @androidx.annotation.DisplayComponent class * {*;}
    

    מומלץ לתת להערות שמות שיספקו הקשר משמעותי לגבי הסיבה לשמירת חלקי הקוד. לדוגמה, אפשר להשתמש ב-@DisplayComponent באפליקציה שבה רכיבי התצוגה דורשים לשמור חלקים מסוימים.

  • בכל מקרה שאפשר, צריך להצהיר על הגדרת החברים, ולהפנות רק לחלקים של המחלקה שצריך לשמור כדי שהאפליקציה תפעל. מומלץ לא להחיל כלל על כיתה שלמה על ידי הגדרת היקף החברים האופציונלי כ-{ *; }, אלא אם יש בכך צורך מובהק.

    -keepclassmembers com.example.MyClass {
      void someSpecificMethod();
      void @com.example.MyAnnotation *;
    }
    
  • אם אתם משתמשים באפשרות הגלובלית repackageclasses, אל תציינו את שם החבילה האופציונלי. כתוצאה מכך, קובצי ה-DEX קטנים יותר כי התחילית של החבילה מושמטת בשמות המחלקות שנארזו מחדש.

אם אתם לא יכולים לפעול בהתאם להנחיות האלה, אתם יכולים לבודד באופן זמני את הקוד שצריך לשמור בחבילה ייעודית ולהחיל את כלל השמירה על החבילה. עם זאת, זה לא פתרון לטווח ארוך. מידע נוסף זמין במאמר בנושא הטמעה הדרגתית של אופטימיזציות. כדי להשתמש בכלל שמירה לחבילה, מגדירים כלל שמירה כמו בדוגמה הבאה:

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

דברים שכדאי להימנע מהם

יש הרבה אפשרויות לכללי השמירה, אבל כדי ליהנות משיפורים מדידים וקבועים בביצועים, אנחנו ממליצים לא להשתמש באפשרויות הבאות:

  • מומלץ להימנע משימוש באופרטור ההיפוך ! בכללי השמירה, כי יכול להיות שתחילו כלל על כמעט כל מחלקה באפליקציה שלכם בלי להתכוון.
  • אל תשתמשו בכללי שמירה שחלים על כל החבילה, כמו -keep class com.example.pkg.** { *; } long-term. אפשר להשתמש בהן באופן זמני כדי לעקוף בעיות בהגדרת R8. מידע נוסף זמין במאמר בנושא הגבלת היקף האופטימיזציה. באופן כללי, צריך להיזהר עם תווים כלליים – חשוב לוודא ששומרים רק את הקוד שצריך.

אם אתם לא מצליחים לפעול לפי הכללים האלה, יכול להיות שאתם משתמשים בהרבה השתקפויות פתוחות, ולכן כדאי להימנע מהשתקפות או מהספרייה באמצעות השתקפות (ראו את מחקר המקרה של Gson).