אופטימיזציה לכותבי ספריות

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

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

מפתחים של אפליקציות שרוצים לקבל מידע על אופטימיזציה של אפליקציות ל-Android יכולים לעיין במאמר הפעלת אופטימיזציה של אפליקציות. במאמר בחירת ספריות בצורה מושכלת מוסבר אילו ספריות מתאימות לשימוש.

שימוש ב-codegen במקום ב-reflection

במידת האפשר, מומלץ להשתמש ביצירת קוד (codegen) במקום ברפלקציה. יצירת קוד (codegen) והשתקפות (reflection) הן שתי גישות נפוצות להימנעות מקוד סטנדרטי בזמן התכנות, אבל יצירת קוד תואמת יותר למטמיע אפליקציות כמו R8:

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

בספריות מודרניות רבות נעשה שימוש ב-codegen במקום ב-reflection. KSP הוא נקודת כניסה נפוצה שמשמשת את Room, את Dagger2 ועוד רבים.

מתי אפשר להשתמש בהשתקפות

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

  • סוגי טירגוט ספציפיים (ממשקי משנה או מפתחי ממשק ספציפיים)
  • קוד עם הערה ספציפית בסביבת זמן הריצה

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

צורת ההשתקפות הספציפית והממוקדת הזו היא דפוס שאפשר לראות גם במסגרת של Android (לדוגמה, כשמנפחים פעילויות, תצוגות ורכיבי drawable) וגם בספריות AndroidX (לדוגמה, כשיוצרים WorkManager ListenableWorkers או RoomDatabases). לעומת זאת, ההשתקפות הפתוחה של Gson לא מתאימה לשימוש באפליקציות ל-Android.

כתיבת כללים לשמירת נתוני הצרכן

בספריות צריך לארוז כללי שמירה של 'צרכן', שמשתמשים באותו פורמט של כללי שמירה של אפליקציות. הכללים האלה מקובצים בפריטי ספרייה (קבצי AAR או JAR) ומנוצלים באופן אוטומטי במהלך האופטימיזציה של אפליקציות ל-Android כשמשתמשים בספרייה.

ספריות AAR

כדי להוסיף כללי צרכן לספריית AAR, משתמשים באפשרות consumerProguardFiles בסקריפט ה-build של מודול הספרייה של Android. למידע נוסף, קראו את ההנחיות שלנו ליצירת מודולים של ספריות.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

Groovy

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

ספריות JAR

כדי לארוז כללים עם ספריית Kotlin/Java שנשלחת כקובץ JAR, צריך להוסיף את קובץ הכללים לתיקייה META-INF/proguard/ של קובץ ה-JAR הסופי, עם כל שם קובץ. לדוגמה, אם הקוד נמצא ב-<libraryroot>/src/main/kotlin, צריך להציב קובץ כללים של צרכן ב-<libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro והכללים יקובצו במיקום הנכון בקובץ ה-JAR של הפלט.

מוודאים שהכללים נכללים בחבילת ה-JAR הסופית בצורה נכונה, על ידי בדיקה שהם נמצאים בספרייה META-INF/proguard.

תמיכה בתוכנות שונות לדחיסת קבצים (מתקדם)

אפשר להתאים אישית את הכללים כך שיטרגו לחבילות דחיסה ספציפיות (R8 או ProGuard), וגם לגרסאות ספציפיות של חבילת דחיסה. כך הספרייה תוכל לפעול בצורה אופטימלית בפרויקטים שמשתמשים בגרסאות חדשות של ה-shrinker, ועדיין יהיה אפשר להשתמש בכללים הקיימים בפרויקטים עם גרסאות ישנות יותר של ה-shrinker.

כדי לציין כללי דחיסה ממוקדים, צריך לכלול אותם במיקומים ספציפיים בתוך ספריית AAR או JAR, כפי שמתואר בהמשך.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

כלומר, כללי הצמצום המטורגטים נשמרים בספרייה META-INF/com.android.tools של קובץ JAR או בספרייה META-INF/com.android.tools בתוך classes.jar של קובץ AAR.

בספרייה הזו יכולות להיות כמה ספריות עם שמות בפורמט r8-from-<X>-upto-<Y> או proguard-from-<X>-upto-<Y>, כדי לציין לאילו גרסאות של אילו מכשירי דחיסה נכתבו הכללים בספריות. שימו לב שהחלקים -from-<X> ו--upto-<Y> הם אופציונליים, הגרסה <Y> היא בלעדית וטווחי הגרסאות חייבים להיות רציפים.

לדוגמה, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 ו-r8-from-8.2.0 יוצרים קבוצה תקינה של כללי צמצום ממוקדים. הכללים שבספרייה r8-from-8.0.0-upto-8.2.0 ישמשו את R8 מגרסה 8.0.0 ועד לגרסה 8.2.0 לא כולל.

על סמך המידע הזה, הפלאגין של Android Gradle בוחר את הכללים מהספריות התואמות של R8. אם בספרייה לא צוינו כללים ספציפיים לצמצום, הפלאגין של Android Gradle יבחר את הכללים מהמיקומים הקודמים (proguard.txt עבור קובץ AAR או META-INF/proguard/<ProGuard-rules-file> עבור קובץ JAR).