כשמפעילים אופטימיזציה של אפליקציות עם הגדרות ברירת המחדל, R8 מבצע אופטימיזציות נרחבות כדי למקסם את יתרונות הביצועים. R8 מבצע שינויים משמעותיים בקוד, כולל שינוי שמות, העברה והסרה של מחלקות, שדות ושיטות. אם אתם מבחינים שהשינויים האלה גורמים לשגיאות, אתם צריכים לציין אילו חלקים בקוד R8 לא צריך לשנות, על ידי הצהרה עליהם בכללי השמירה.
תרחישים נפוצים שבהם נדרשים כללי שמירה
R8 מזהה ושומר את כל הקריאות הישירות בקוד. עם זאת, R8 לא יכול לראות שימושים עקיפים בקוד, ולכן הוא עלול להסיר קוד שהאפליקציה צריכה, מה שגורם לקריסות. כדי להנחות את R8 לשמור קוד כזה שנעשה בו שימוש באופן עקיף, צריך להשתמש בכללי שמירה. הנה כמה מצבים נפוצים שבהם כנראה תצטרכו כללי שמירה:
- קוד שהגישה אליו מתבצעת באמצעות רפלקציה: R8 לא יכול לזהות מתי מתבצעת גישה למחלקות, לשדות או למתודות באמצעות רפלקציה. לדוגמה, R8 לא יכול לזהות שיטה שחיפשו אותה לפי השם שלה באמצעות
Class.getDeclaredMethod()או הערה שאוחזרה באמצעותClass.getAnnotation(). במקרים כאלה, יכול להיות שהכלי R8 ישנה את השמות של השיטות וההערות האלה או יסיר אותן לגמרי, מה שיוביל ל-ClassNotFoundExceptionאו ל-NoSuchMethodExceptionבזמן הריצה. - קוד שנקרא מ-Java Native Interface (JNI): כשקוד מקורי (C או ++C) קורא ל-method של Java או Kotlin, או כשקוד של Java או Kotlin קורא לקוד של ++C באמצעות JNI, הקריאה מבוססת על חיפוש מחרוזת דינמי של שם ה-method. R8 לא יכול לראות את הקריאה לשיטה דינמית שמבוססת על מחרוזת, ולכן האופטימיזציות שלו עלולות לשבור את הקוד.
זו לא רשימה מלאה של תרחישים שבהם נדרשים כללי שמירה, אבל התרחישים האלה מכסים את רוב המקרים שבהם יכול להיות שתצטרכו כללי שמירה.
אם הקוד שלכם משתמש ברפלקציה או נקרא מ-JNI, אתם יכולים להוסיף לקוד הערות Jetpack Keep במקום לכתוב כללי שמירה באופן ידני. תוסף Gradle שלו יוצר את כללי השמירה מההערות בזמן הבנייה.
איך מוסיפים כללי שמירה לאפליקציה
ההגדרה של כללי השמירה תלויה בגרסה של AGP שבה אתם משתמשים.
באפליקציות גדולות יותר, הקוד נמצא בדרך כלל בכמה מודולים של ספריות. במקרים כאלה, עדיף בדרך כלל להציב את כללי השמירה לצד הקוד שהם חלים עליו במודול הספציפי של הספרייה. ההבדל המהותי בשמירה של כללי שמירה בספריות הוא באופן ההצהרה על הכללים האלה בקובץ build.gradle.kts (או build.gradle) של מודול הספרייה. מידע נוסף זמין במאמר אופטימיזציה למפתחי ספריות.
בגרסאות AGP 9.3 ואילך
מוסיפים את הכללים לקובץ עם הסיומת .keep בספרייה src/<variant>/keepRules. לדוגמה: src/main/keepRules/custom-rules.keep. שימו לב: שימוש ב-DSL המעודכן ל-AGP בגרסה 9.3 ואילך מאפשר אופטימיזציה של קוד ומשאבים, ולא מחייב אתכם להגדיר במפורש את קובץ ברירת המחדל של כללי השמירה ב-Android (proguard-android-optimize.txt), כי הוא נכלל כברירת מחדל, אלא אם הוא מושמט במפורש.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
מגניב
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
השמטת כללי השמירה שמוגדרים כברירת מחדל בפלטפורמת Android (מתקדם)
AGP מספק קבוצה של כללי ברירת מחדל לפלטפורמת Android. כדי להשמיט את הכללים האלה מההגדרות של הפרויקט ולנהל את כל כללי השמירה בעצמכם, מגדירים את optimization.keepRules.includeDefault לערך false.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
מגניב
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
DSL מדור קודם לגרסאות AGP ישנות יותר מ-9.3
מוסיפים את הכללים לקובץ proguard-rules.pro שנמצא בתיקיית השורש של מודול האפליקציה. יכול להיות שהקובץ כבר נמצא שם, אבל אם לא, צריך ליצור אותו. כדי להחיל את הכללים שבקובץ, צריך להצהיר על הקובץ בקובץ build.gradle.kts (או build.gradle) ברמת המודול.
כברירת מחדל, קובץ ה-build כולל גם את הקובץ proguard-android-optimize.txt. הקובץ הזה כולל כללים שנדרשים לרוב הפרויקטים ב-Android, אז כדאי להשאיר אותו בקובץ ה-build. הקובץ הזה מבוסס על הקובץ proguard-common.txt וכולל תוכן שמשותף איתו.
DSL מדור קודם (Kotlin)
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
// Default file with default optimization rules.
getDefaultProguardFile("proguard-android-optimize.txt"),
...
)
}
}
}
DSL מדור קודם (Groovy)
android {
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
// Default file with default optimization rules.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
...
}
}
}
הוספת כלל שמירה
כשמוסיפים כללי שמירה, אפשר לכלול אפשרויות גלובליות וגם להגדיר כללי שמירה משלכם.
הגדרות גלובליות: הגדרות גלובליות הן הנחיות כלליות שמשפיעות על האופן שבו R8 פועל בכל בסיס הקוד. מידע נוסף זמין במאמר אפשרויות גלובליות.
כללי שמירה: צריך לתכנן את כללי השמירה בקפידה כדי לוודא שאתם מגיעים לאיזון הנכון בין מקסימום אופטימיזציה של הקוד לבין שמירה על האפליקציה מפני תקלות לא מכוונות. כדי ללמוד איך לכתוב כללי שמירה, קראו את המאמר הוספת כללי שמירה.
כללי שמירה למחברי ספריות
אחרי שתלמדו על ההגדרות הגלובליות והתחביר של כללי השמירה, תוכלו לקרוא מידע נוסף במאמר אופטימיזציה למפתחי ספריות.