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

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

דוגמאות טובות לכללי שמירה

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

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

    -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).