בפיתוח מודרני של אפליקציות ל-Android, משתמשים מצפים לקבל אפליקציה קטנה, מהירה ומאובטחת. הכלי העיקרי במערכת ה-build של Android להשגת המטרה הזו הוא R8 , כלי האופטימיזציה, הקומפיילר שמטפל בהסרה של קוד לא פעיל ומשאבים לצורך כיווץ, שינוי שם של קוד או הקטנה, ואופטימיזציה של האפליקציה.
הפעלת R8 היא שלב חשוב בהכנת אפליקציה לפרסום, אבל היא מחייבת את המפתחים לספק הנחיות בצורה של 'כללי שמירה'.
אחרי שתקראו את המאמר הזה, כדאי לצפות בסרטון 'הדגשת ביצועים: שבוע' ב-YouTube כדי ללמוד איך להפעיל את הכלי לשיפור הביצועים R8, איך לנפות באגים ואיך לפתור בעיות.
למה צריך כללים לשמירת נתונים ב-Keep
הצורך בכתיבת כללי Keep נובע מסתירה מהותית: R8 הוא כלי לניתוח סטטי, אבל אפליקציות ל-Android מסתמכות לעיתים קרובות על דפוסי ביצוע דינמיים כמו רפלקציה או קריאות אל קוד Native וממנו באמצעות JNI (Java Native Interface).
R8 יוצר גרף של קוד בשימוש על ידי ניתוח של קריאות ישירות. כשניגשים לקוד באופן דינמי, הניתוח הסטטי של R8 לא יכול לחזות את זה, והוא יזהה את הקוד כלא בשימוש ויסיר אותו, מה שיוביל לקריסות בזמן הריצה.
כלל שמירה הוא הוראה מפורשת לקומפיילר R8, שבה מצוין: "המחלק, השיטה או השדה הספציפיים האלה הם נקודת כניסה שתהיה נגישה באופן דינמי בזמן הריצה. אתם חייבים לשמור אותו, גם אם אתם לא מוצאים הפניה ישירה אליו".
מידע נוסף על כללי השמירה זמין במדריך הרשמי.
איפה כותבים כללים ל-Keep
כללי שמירה מותאמים אישית לאפליקציה נכתבים בקובץ טקסט. לפי המוסכמה, שם הקובץ הוא proguard-rules.pro והוא נמצא בבסיס של מודול האפליקציה או הספרייה. לאחר מכן מציינים את הקובץ הזה בסוג ה-build release של קובץ build.gradle.kts של המודול.
release {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
שימוש בקובץ ברירת המחדל הנכון
השיטה getDefaultProguardFile מייבאת קבוצת כללים שמוגדרת כברירת מחדל ומסופקת על ידי Android SDK. אם משתמשים בקובץ לא מתאים, יכול להיות שהאפליקציה לא תעבור אופטימיזציה. חשוב להשתמש ב-proguard-android-optimize.txt. הקובץ הזה מספק את כללי השמירה שמוגדרים כברירת מחדל לרכיבי Android רגילים ומאפשר אופטימיזציות של קוד ב-R8. הגרסה המיושנת של proguard-android.txt מספקת רק את כללי השמירה, אבל לא מאפשרת את האופטימיזציות של R8.
זו בעיה חמורה בביצועים, ולכן אנחנו מתחילים להזהיר מפתחים מפני שימוש בקובץ הלא נכון, החל מ-Android Studio Narwhal 3 Feature Drop. החל מגרסה 9.0 של פלאגין Android Gradle, אנחנו כבר לא תומכים בקובץ proguard-android.txt המיושן. לכן חשוב לשדרג לגרסה המותאמת.
איך כותבים כללים ב-Keep
כלל שמירה מורכב משלושה חלקים עיקריים:
- אפשרות כמו
-keepאו-keepclassmembers - מגבילים אופציונליים כמו
allowshrinking - מפרט כיתה שמגדיר את הקוד להתאמה
לעיון בתחביר המלא ובדוגמאות, אפשר לעיין בהנחיות בנושא הוספת כללי שמירה.
שמירה על כללי אנטי-תבניות
חשוב להכיר שיטות מומלצות, אבל גם דפוסים בעייתיים. האנטי-דפוסים האלה נובעים לרוב מאי-הבנות או מקיצורי דרך לפתרון בעיות, והם עלולים לפגוע באופן משמעותי בביצועים של גרסת ייצור.
אפשרויות כלליות
הדגלים האלה הם מתגים גלובליים שאסור בשום אופן להשתמש בהם בגרסת build להפצה. הם מיועדים לניפוי באגים זמני בלבד, כדי לבודד בעיה.
השימוש ב- -dontotptimize משבית למעשה את האופטימיזציות של R8 לשיפור הביצועים, וכתוצאה מכך האפליקציה פועלת לאט יותר.
כשמשתמשים ב--dontobfuscate, כל הפעולות של שינוי השם מושבתות, וכשמשתמשים ב--dontshrink, ההסרה של קוד לא פעיל מושבתת. שני הכללים הגלובליים האלה מגדילים את גודל האפליקציה.
כדי לשפר את חוויית המשתמש באפליקציה, מומלץ להימנע משימוש בדגלים הגלובליים האלה בסביבת ייצור, ככל האפשר.
כללי שמירה רחבים מדי
הדרך הכי קלה לבטל את היתרונות של R8 היא לכתוב כללי שמירה רחבים מדי. כללים כמו זה שבהמשך מנחים את כלי האופטימיזציה R8 לא לכווץ, לא להצפין ולא לבצע אופטימיזציה לאף מחלקה בחבילה הזו או לאף אחת מחבילות המשנה שלה. הפעולה הזו מסירה לחלוטין את היתרונות של R8 מהחבילה כולה. במקום זאת, כדאי לנסות לכתוב כללי שמירה ספציפיים ומצומצמים יותר.
-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMS
אופרטור ההיפוך (!)
נראה שאופרטור ההיפוך (!) הוא דרך יעילה להחרגת חבילה מכלל. אבל זה לא כל כך פשוט. לדוגמה:
-keep class !com.example.my_package.** { *; } // USE WITH CAUTION
יכול להיות שתחשבו שהכלל הזה אומר "לא לשמור כיתות ב-com.example.package". אבל למעשה הוא אומר "לשמור כל כיתה, שיטה ומאפיין בכל האפליקציה שלא נמצאים ב- com.example.package". אם זה הפתיע אתכם, כדאי לבדוק אם יש שלילות בהגדרות של R8.
כללים מיותרים לרכיבי Android
טעות נפוצה נוספת היא הוספה ידנית של כללי שמירה עבור Activities, Services או BroadcastReceivers של האפליקציה. זה לא נחוץ. קובץ proguard-android-optimize.txt שמוגדר כברירת מחדל כבר כולל את הכללים הרלוונטיים לרכיבי Android הרגילים האלה, כדי שהם יפעלו ללא צורך בהגדרה נוספת.
בנוסף, ספריות רבות מביאות איתן כללי שמירה משלהן. לכן לא צריך לכתוב כללים משלכם בשביל זה. אם יש בעיה בכללי השמירה בספרייה שבה אתם משתמשים, מומלץ לפנות ליוצר הספרייה כדי לברר מה הבעיה.
שיטות מומלצות לשימוש בכללים
אחרי שהסברנו מה לא לעשות, נדבר על שיטות מומלצות.
כתיבת כללים ספציפיים ב-Keep
כללי שמירה טובים ב-Keep צריכים להיות מצומצמים וספציפיים ככל האפשר. הם צריכים לשמור רק את מה שנדרש, כדי לאפשר ל-R8 לבצע אופטימיזציה לכל השאר.
| כלל | איכות |
|---|---|
| נמוך: שומר את כל החבילה ואת חבילות המשנה שלה |
| נמוך: שומר על כיתה שלמה, שסביר להניח שהיא עדיין רחבה מדי |
-keepclassmembers class com.example.MyClass {
private java.lang.String secretMessage;
public void onNativeEvent(java.lang.String);
}
| גבוהה: נשמרים רק המאפיינים והשיטות הרלוונטיים ממחלקה ספציפית |
שימוש באבות משותפים
במקום לכתוב כללי שמירה נפרדים לכמה מודלים שונים של נתונים, כדאי לכתוב כלל אחד שמכוון לממשק או למחלקת בסיס משותפת. הכלל שמופיע בהמשך אומר ל-R8 לשמור את כל החברים במחלקות שמיישמות את הממשק הזה, והוא ניתן להרחבה בקלות.
# Keep all fields of any class that implements SerializableModel
-keepclassmembers class * implements com.example.models.SerializableModel {
<fields>;
}
שימוש בהערות כדי לטרגט מספר כיתות
יוצרים הערה בהתאמה אישית (לדוגמה, @Serialize) ומשתמשים בה כדי 'לתייג' מחלקות שצריך לשמור את השדות שלהן. זהו עוד דפוס נקי, הצהרתי וניתן להרחבה. אתם יכולים גם ליצור כללי Keep להערות שכבר קיימות מתוך מסגרות שבהן אתם משתמשים.
# Keep all fields of any class annotated with @Serialize
-keepclassmembers class * {
@com.example.annotations.Serialize <fields>;
}
בחירת האפשרות המתאימה ב-Keep
האפשרות Keep (שמירה) היא החלק הכי חשוב בכלל. בחירה לא נכונה עלולה להשבית את האופטימיזציה ללא צורך.
| אפשרות Keep | מה קורה כשמשתמשים במצב פרטי |
-keep | מונע את ההסרה או השינוי של השם של המחלקה ושל החברים שמוזכרים בהצהרה . |
-keepclassmembers | מונעת את ההסרה או את שינוי השם של החברים שצוינו, אבל מאפשרת את ההסרה של הכיתה עצמה, רק בכיתות שלא הוסרו בדרך אחרת. |
-keepclasseswithmembers | שילוב: הכיתה וגם התלמידים שבה יישמרו, רק אם כל התלמידים שצוינו נמצאים בה. |
מידע נוסף על האפשרות 'שמירה' זמין במאמר בנושא אפשרויות השמירה.
אופטימיזציה עם משנים
משנים כמו allowshrinking ו-allowobfuscation מרחיבים כלל -keep, ומאפשרים ל-R8 לבצע אופטימיזציה. לדוגמה, אם ספרייה מדור קודם מחייבת אתכם להשתמש ב--keep במחלקה שלמה, יכול להיות שתוכלו לשפר את האופטימיזציה על ידי הפעלת כיווץ והסתרה:
# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it. -keep,allowshrinking,allowobfuscation class com.example.LegacyClass
הוספת הגדרות גלובליות להוספת אופטימיזציה
בנוסף לכללי Keep, אפשר להוסיף דגלים גלובליים לקובץ ההגדרות של R8 כדי לעודד אופטימיזציה נוספת.
-repackageclasses היא אפשרות עוצמתית שמורה ל-R8 להעביר את כל המחלקות המוסתרות לחבילה אחת. הפעולה הזו חוסכת נפח משמעותי בקובץ ה-DEX, כי היא מסירה מחרוזות מיותרות של שמות חבילות.
-allowaccessmodification מאפשרת ל-R8 להרחיב את הגישה (למשל, private ל- public) כדי לאפשר הטמעה אגרסיבית יותר. האפשרות הזו מופעלת עכשיו כברירת מחדל כשמשתמשים ב-proguard-android-optimize.txt.
אזהרה: מפתחי ספריות אף פעם לא צריכים להוסיף את דגלי האופטימיזציה הגלובליים האלה לכללי הצרכן שלהם, כי הם יחולו בכפייה על כל האפליקציה.
כדי להבהיר את העניין עוד יותר, בגרסה 9.0 של פלאגין של Android Gradle נתחיל להתעלם לחלוטין מדגלי אופטימיזציה גלובליים של ספריות.
שיטות מומלצות לשימוש בספריות
כל אפליקציית Android מסתמכת על ספריות בדרך כזו או אחרת. בואו נדבר על שיטות מומלצות לספריות.
למפתחי ספריות
אם הספרייה משתמשת ב-reflection או ב-JNI, אתם אחראים לספק למשתמשים שלה את כללי השמירה הנדרשים. הכללים האלה ממוקמים בקובץ consumer-rules.pro, שמאוגד אוטומטית בתוך קובץ ה-AAR של הספרייה.
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
...
}
למשתמשים בספרייה
סינון כללי Keep בעייתיים
אם אתם חייבים להשתמש בספרייה שכוללת כללי שמירה בעייתיים, אתם יכולים לסנן אותם בקובץ build.gradle.kts החל מ-AGP 9.0. כך מערכת R8 מתעלמת מהכללים שמגיעים מהתלות הספציפית.
release {
optimization.keepRules {
// Ignore all consumer rules from this specific library
it.ignoreFrom("com.somelibrary:somelibrary")
}
}
הכלל הכי טוב ב-Keep הוא לא להגדיר כלל בכלל
האסטרטגיה האולטימטיבית להגדרת R8 היא להימנע לחלוטין מהצורך לכתוב כללי שמירה. במקרים רבים, אפשר להשיג זאת על ידי בחירה בספריות מודרניות שמעדיפות יצירת קוד על פני רפלקציה. בעזרת יצירת קוד, הכלי לאופטימיזציה יכול לקבוע בקלות רבה יותר איזה קוד נמצא בשימוש בזמן הריצה ואיזה קוד אפשר להסיר. בנוסף, אם לא משתמשים בהשתקפות דינמית, אין נקודות כניסה 'מוסתרות', ולכן לא צריך כללי שמירה. כשבוחרים ספרייה חדשה, תמיד עדיף לבחור פתרון שמשתמש ביצירת קוד ולא ברפלקציה.
מידע נוסף על בחירת ספריות זמין במאמר בחירה נכונה של ספריות.
ניפוי באגים ופתרון בעיות בהגדרת R8
אם R8 מסיר קוד שהיה צריך להישאר, או אם קובץ ה-APK גדול מהצפוי, אפשר להשתמש בכלים האלה כדי לאבחן את הבעיה.
איתור כללי שמירה כפולים וכללי שמירה גלובליים
מכיוון ש-R8 ממזג כללים מעשרות מקורות, יכול להיות שיהיה קשה לדעת מהו קבוצת הכללים הסופית. הוספת הדגל הזה לקובץ proguard-rules.pro יוצרת דוח מלא:
# Outputs the final, merged set of rules to the specified file -printconfiguration build/outputs/logs/configuration.txt
אפשר לחפש בקובץ הזה כללים מיותרים או לעקוב אחרי כלל בעייתי (כמו -dontoptimize) עד לספרייה הספציפית שכוללת אותו.
תשובה של R8: למה אתה שומר את זה?
אם כיתה שציפיתם שהיא תוסר עדיין מופיעה באפליקציה, R8 יכול להסביר לכם למה. פשוט מוסיפים את הכלל הזה:
# Asks R8 to explain why it's keeping a specific class class com.example.MyUnusedClass -whyareyoukeeping
במהלך הבנייה, R8 ידפיס את שרשרת ההפניות המדויקת שגרמה לו לשמור את המחלקה הזו, וכך תוכלו לעקוב אחרי ההפניה ולשנות את הכללים.
מדריך מלא זמין בקטע פתרון בעיות ב-R8.
השלבים הבאים
R8 הוא כלי יעיל לשיפור ביצועי האפליקציה ב-Android. היעילות שלו תלויה בהבנה נכונה של אופן הפעולה שלו כמנוע ניתוח סטטי.
כדי לשמור בדיוק את מה שצריך, אפשר לכתוב כללים ספציפיים ברמת החבר, להשתמש בנתוני צאצאים ובהערות, ולבחור בקפידה את אפשרויות השמירה הנכונות. השיטה המתקדמת ביותר היא לבטל את הצורך בכללים לחלוטין, על ידי בחירה בספריות מודרניות שמבוססות על יצירת קוד, במקום בספריות קודמות שמבוססות על רפלקציה.
במהלך שבוע ההמלצות לשיפור הביצועים, כדאי לצפות בסרטון של היום ב-YouTube ולהמשיך עם האתגר R8 שלנו. אם יש לכם שאלות לגבי הפעלה או פתרון בעיות ב-R8, תוכלו להשתמש בתג #optimizationEnabled. אנחנו פה לשירותך.
הגיע הזמן לראות את היתרונות בעצמכם.
אנחנו ממליצים להפעיל את המצב המלא של R8 באפליקציה עוד היום.
- כדי להתחיל, כדאי לעיין במדריכים למפתחים: הפעלת אופטימיזציה של אפליקציות.
- בודקים אם אתם עדיין משתמשים ב-
proguard-android.txtומחליפים אותו ב-proguard-android-optimize.txt. - לאחר מכן, מודדים את ההשפעה. אל תסתפקו בתחושה של הבדל, בדקו אותו. כדי למדוד את השיפור בביצועים, אפשר להתאים את הקוד מ אפליקציית הדוגמה Macrobenchmark ב-GitHub כדי למדוד את זמני ההפעלה לפני ואחרי.
אנחנו בטוחים שתראו שיפור משמעותי בביצועים של האפליקציה.
אתם יכולים גם להשתמש בתג #AskAndroid ברשתות החברתיות כדי לשאול שאלות. במהלך השבוע המומחים שלנו בודקים את השאלות שלכם ועונים עליהן.
מחר נדבר על אופטימיזציה מונחית פרופיל באמצעות פרופילים של Baseline ו-Startup, נסביר איך השתפרו ביצועי העיבוד של Compose בגרסאות האחרונות ונשתף שיקולים לגבי ביצועים של עבודה ברקע.
להמשך הקריאה
-
חדשות על מוצרים
הסביבה העסקית של הנייד מתפתחת כל הזמן, ומביאה איתה הזדמנויות חדשות וגם איומים חדשים. בעקבות השינויים האלה, אנחנו ב-Android וב-Google Play ממשיכים לפעול כדי להבטיח שמיליארדי משתמשים יוכלו להמשיך ליהנות מהאפליקציות שלהם בביטחון, ושהמפתחים יוכלו להמשיך לחדש.
Vijaya Kaza • משך הקריאה: 3 דקות
-
חדשות על מוצרים
גרסת Jetpack פיתוח נייטיב מאפריל 2026 היא יציבה. הגרסה הזו מכילה את גרסה 1.11 של מודולי הליבה של Compose (ראו את מיפוי ה-BOM המלא), כלי ניפוי באגים של רכיבים משותפים, אירועים של משטח מגע ועוד.
Meghan Mehta • משך הקריאה: 5 דקות
-
חדשות על מוצרים
גרסה Panda 4 של Android Studio יציבה ומוכנה לשימוש בייצור. הגרסה הזו כוללת את מצב התכנון, את התחזית לגבי העריכה הבאה ועוד, וכך קל יותר מאי פעם ליצור אפליקציות Android באיכות גבוהה.
Matt Dyor • משך הקריאה: 5 דקות
כדאי תמיד להיות בעניינים
רוצים לקבל טיפים עדכניים לפיתוח Android ישירות לאימייל כל שבוע?