כדי לספק את חוויית המשתמש הטובה ביותר, מומלץ לבצע אופטימיזציה של האפליקציה כדי שהיא תהיה קטנה ומהירה ככל האפשר. כלי האופטימיזציה של האפליקציה שלנו, שנקרא R8, מייעל את האפליקציה על ידי הסרת קוד ומשאבים שלא נמצאים בשימוש, כתיבה מחדש של קוד כדי לבצע אופטימיזציה של ביצועי זמן הריצה ועוד. למשתמשים שלכם, המשמעות היא:
- זמן הפעלה מהיר יותר
- שימוש מופחת בזיכרון
- שיפורים בביצועי העיבוד והזמן של הריצה
- פחות מקרי ANR
סקירה כללית על אופטימיזציה של R8
R8 משתמש בתהליך רב-שלבי כדי לבצע אופטימיזציה של האפליקציה מבחינת הגודל והמהירות שלה. בין הפעולות העיקריות:
כיווץ קוד (שנקרא גם tree shaking): R8 מזהה ומסיר קוד שלא ניתן להגיע אליו מהאפליקציה ומהתלות שלה בספריות. על ידי ניתוח נקודות הכניסה של האפליקציה (כמו
ActivitiesאוServicesשמוגדרות במניפסט), R8 יוצר גרף של קוד עם הפניות ומסיר כל מה שלא נשאר עם הפניות.אופטימיזציות לוגיות: R8 כותב מחדש את הקוד כדי לשפר את יעילות הביצוע ולהפחית את התקורה. בין הטכניקות העיקריות:
הטמעה של שיטות: R8 מחליף אתר של הפעלת method בגוף בפועל של השיטה שנקראה. כך נחסכים התקורה של בקשה להפעלת פונקציה, ו-R8 יכול לבצע אופטימיזציות נוספות.
מיזוג מחלקות: R8 משלב קבוצות של מחלקות וממשקים למחלקה אחת. כך מצטמצם מספר המחלקות באפליקציה, העומס על הזיכרון פוחת ומהירות ההפעלה משתפרת.
ערפול קוד (obfuscation) (נקרא גם minification): כדי להקטין את הגודל של קובץ ה-DEX, R8 מקצר את השמות של המחלקות, השדות והשיטות (לדוגמה,
com.example.MyActivityיכול להפוך ל-a.b.a).
החל מגרסה 8.12.0 של פלאגין של Android Gradle (AGP), R8 גם מבצע אופטימיזציה של משאבים כחלק משלבי האופטימיזציה שלו. מידע נוסף זמין במאמר בנושא כיווץ מקורות המידע בצורה אופטימלית.
הפעלת אופטימיזציה
כדי להפעיל אופטימיזציה של האפליקציה, צריך להגדיר את isMinifyEnabled = true (לאופטימיזציה של קוד) ואת isShrinkResources = true (לאופטימיזציה של משאבים) בסקריפט הבנייה ברמת האפליקציה של גרסת build להפצה, כמו שמוצג בקוד הבא. מומלץ להפעיל תמיד את שתי ההגדרות. מומלץ גם להפעיל אופטימיזציה של האפליקציה רק בגרסה הסופית של האפליקציה שבודקים לפני הפרסום – בדרך כלל גרסת build להפצה – כי האופטימיזציות מאריכות את משך זמן של תהליך build של הפרויקט ויכולות להקשות על ניפוי הבאגים בגלל האופן שבו הן משנות את הקוד.
Kotlin
android { buildTypes { release { // Enables code-related app optimization. isMinifyEnabled = true // Enables resource shrinking. isShrinkResources = true proguardFiles( // Default file with automatically generated optimization rules. getDefaultProguardFile("proguard-android-optimize.txt"), ... ) ... } } ... }
מגניב
android { buildTypes { release { // Enables code-related app optimization. minifyEnabled = true // Enables resource shrinking. shrinkResources = true // Default file with automatically generated optimization rules. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') ... } } }
שיפור האופטימיזציה של R8
היתרונות בביצועים של R8 קשורים ישירות לכמות בסיס הקוד שאפשר לבצע בו אופטימיזציה באמצעות R8. כדי להפיק את המרב מ-R8, מומלץ לפעול לפי השיטות המומלצות הבאות:
- הפעלת R8 במצב מלא
- הפעלה של ערפול קוד (obfuscation), אופטימיזציה וכיווץ
- הפעלה של כיווץ מקורות מידע וכיווץ מקורות מידע שעבר אופטימיזציה
- כדאי לשפר את כללי השמירה כדי לאפשר אופטימיזציה מקסימלית של מחלקות, שדות ושיטות.
כדי לשפר את כללי השמירה, אפשר להשתמש בכלי לניתוח ההגדרות של R8.
כלי הניתוח של הגדרות R8 מאפשר לכם:
- כדי לעקוב אחרי האיכות הכוללת של הגדרת R8 ולשפר אותה, אפשר לעיין במדדים שמופיעים בדוח של כלי הניתוח של הגדרת R8.
- איך מוצאים את כללי השמירה הרחבים ביותר – אלה שמונעים את רוב האופטימיזציה
- ולהבין איזו אופטימיזציה הם מונעים, כדי לשפר אותם.
כלי הניתוח של הגדרות R8 זמין ב-AGP בגרסה 9.3.0-alpha05 או ב-R8 בגרסה 9.3.7-dev. מידע נוסף זמין במאמר בנושא ניתוח הגדרות R8.
אופטימיזציה של כיווץ משאבים לאפליקציות קטנות עוד יותר
בגרסה 8.12.0 של פלאגין של Android Gradle (AGP) מוצגת אופטימיזציה של צמצום משאבים, שמטרתה לשלב אופטימיזציה של משאבים וקוד כדי ליצור אפליקציות קטנות ומהירות עוד יותר.
לפני האופטימיזציה של צמצום המשאבים, Android Asset Packaging Tool (AAPT2) יצר כללי שמירה שטיפלו בצמצום המשאבים בנפרד מהקוד, ולעתים קרובות שמרו קוד או משאבים שלא הייתה אליהם גישה, או שהייתה הפניה הדדית ביניהם.
בכיווץ מקורות מידע שעבר אופטימיזציה, מקורות מידע נחשבים כחלק מקוד התוכנית ויוצרים את גרף ההפניות. כשלא מתבצעת הפניה לאוסף של קוד או מקורות מידע, הוא לא מוגן על ידי כלל שמירה, ואפשר להסיר אותו.
הפעלה של כיווץ מקורות מידע שעבר אופטימיזציה
כדי להפעיל את צינור ה-**אופטימיזציה** החדש ל**כיווץ מקורות המידע** ב-AGP 8.12 או 8.13, מוסיפים את השורות הבאות לקובץ gradle.properties של ה**פרויקט**:
android.r8.optimizedResourceShrinking=true
אם אתם משתמשים ב-AGP 9.0.0 או בגרסה חדשה יותר, אתם לא צריכים להגדיר את android.r8.optimizedResourceShrinking=true. כיווץ מקורות מידע שעבר אופטימיזציה מוחל באופן אוטומטי כשמפעילים את isShrinkResources = true בהגדרות של הגרסה.
אימות והגדרה של הגדרות האופטימיזציה של R8
כדי לאפשר ל-R8 להשתמש ביכולות האופטימיזציה המלאות שלו, צריך להסיר את השורה הבאה מקובץ gradle.properties של הפרויקט, אם היא קיימת:
android.enableR8.fullMode=false # Remove this line from your codebase.
שימו לב: הפעלת אופטימיזציה של אפליקציות מקשה על ההבנה של עקבות מחסנית, במיוחד אם R8 משנה את השמות של מחלקות או שיטות. כדי לקבל עקבות מחסנית שתואמים בצורה נכונה לקוד המקור, אפשר לעיין במאמר בנושא שחזור עקבות המחסנית המקוריים.
אם R8 מופעל, כדאי גם ליצור פרופילים להפעלה כדי לשפר עוד יותר את ביצועי ההפעלה.
אם הפעלתם אופטימיזציה של אפליקציות והיא גורמת לשגיאות, הנה כמה אסטרטגיות לפתרון הבעיות:
- הוספת כללי שמירה כדי להשאיר חלק מהקוד ללא שינוי.
- הטמעה הדרגתית של אופטימיזציות.
- צריך לעדכן את הקוד כדי להשתמש בספריות שמתאימות יותר לאופטימיזציה.
אם אתם רוצים לייעל את מהירות ה-build, במאמר הגדרת אופן ההפעלה של R8 מוסבר איך להגדיר את R8 בהתאם לסביבה שלכם.
שינויים בהתנהגות של גרסאות AGP ו-R8
בטבלה הבאה מפורטות התכונות העיקריות שהוצגו בגרסאות שונות של פלאגין של Android Gradle (AGP) ושל R8 compiler.
| גרסת AGP | תכונות חדשות |
|---|---|
| 9.1 |
מחלקות שנארזות מחדש כברירת מחדל: R8 אורז מחדש מחלקות (מעביר אותן לחבילה ללא שם, ברמה העליונה) כדי לדחוס עוד יותר את קובץ ה-DEX, וכך אין צורך לציין את האפשרות -repackageclasses. מידע על אופן הפעולה של האפשרות הזו ועל אופן ההשבתה שלה זמין במאמר בנושא אפשרויות גלובליות.
|
| 9.0 |
כיווץ מקורות מידע שעבר אופטימיזציה: מופעל כברירת מחדל (נשלט באמצעות android.r8.optimizedResourceShrinking). כיווץ מקורות מידע שעבר אופטימיזציה עוזר לשלב כיווץ מקורות מידע עם צינור האופטימיזציה של הקוד, וכך ליצור אפליקציות קטנות ומהירות יותר. הכלי מבצע אופטימיזציה של הקוד ושל הפניות למשאבים בו-זמנית, וכך הוא מזהה משאבים שההפניה אליהם היא מקוד שלא נמצא בשימוש ומסיר אותם. זהו שיפור משמעותי לעומת תהליכי האופטימיזציה הנפרדים הקודמים.האפשרות הזו שימושית במיוחד לאפליקציות שמשתפות משאבים וקוד משמעותיים בין ענפים שונים של גורמי צורה, עם שיפורים שנמדדו של יותר מ-50% בגודל האפליקציה. הקטנת הגודל מאפשרת הורדות קטנות יותר, התקנות מהירות יותר וחוויית משתמש טובה יותר עם הפעלה מהירה יותר, עיבוד משופר ופחות שגיאות ANR. סינון כללים של ספריות: הוסרה התמיכה באפשרויות גלובליות (לדוגמה, -dontobfuscate) בכללי צרכן של ספריות, והאפליקציות יסננו אותן. מידע נוסף זמין במאמר בנושא הוספת אפשרויות גלובליות.בדיקות של ערכי null ב-Kotlin: אופטימיזציה מופעלת כברירת מחדל (נשלטת באמצעות -processkotlinnullchecks). בגרסה הזו בוצעו גם שיפורים משמעותיים במהירות ה-build. מידע נוסף זמין במאמר בנושא הגדרות גלובליות להוספת אופטימיזציה.אופטימיזציה של חבילות ספציפיות: אפשר להשתמש ב- packageScope כדי לבצע אופטימיזציה של חבילות ספציפיות. התמיכה הזו ניסיונית. מידע נוסף זמין במאמר בנושא אופטימיזציה של חבילות שצוינו באמצעות packageScope.אופטימיזציה כברירת מחדל: הפסקנו לתמוך ב- getDefaultProguardFile("proguard-android.txt") כי הוא כולל את -dontoptimize, ומומלץ להימנע ממנו. במקום זאת, צריך להשתמש ב-"proguard-android-optimize.txt". אם אתם צריכים להשבית את האופטימיזציה באפליקציה באופן גלובלי, צריך להוסיף את הדגל באופן ידני לקובץ Proguard.
|
| 8.12 |
כיווץ מקורות מידע שעבר אופטימיזציה: נוספה תמיכה ראשונית (נשלט באמצעות android.r8.optimizedResourceShrinking). כיווץ מקורות מידע שעבר אופטימיזציה עוזר לשלב כיווץ מקורות מידע עם צינור האופטימיזציה של הקוד. צריך להפעיל אותה באופן ידני בגרסה הזו של AGP.Logcat retracing: Support for automatic retracing in the Android Studio Logcat window. |
| 8.6 |
שיפורים באיתור מקורות: כולל איתור מקורות לפי שם הקובץ ומספר השורה כברירת מחדל לכל הרמות של minSdk (בעבר נדרשה רמה של minSdk 26 ומעלה בגרסה 8.2).עדכון של R8 עוזר לוודא שקובצי מעקב אחר ביצועים (stack traces) מגרסאות obfuscated ניתנים לקריאה בקלות ובבירור. בגרסה הזו שיפרנו את המיפוי של מספרי השורות וקבצי המקור, כדי שיהיה קל יותר לכלים כמו Logcat ב-Android Studio לאתר באופן אוטומטי את הגורם לקריסות בקוד המקור המקורי. |
| 8.0 |
מצב מלא כברירת מחדל: המצב המלא של R8 מספק אופטימיזציה חזקה משמעותית. ההגדרה הזו מופעלת כברירת מחדל. אפשר לבטל את ההצטרפות באמצעות android.enableR8.fullMode=false.
|
| 7.0 |
מצב מלא זמין: השקנו את התכונה הזו כאפשרות הצטרפות באמצעות android.enableR8.fullMode=true. במצב מלא, המערכת מבצעת אופטימיזציות חזקות יותר על ידי הנחה של הנחות מחמירות יותר לגבי האופן שבו הקוד משתמש בהשתקפות ובתכונות דינמיות אחרות. השימוש ב-ProGuard מקטין את גודל האפליקציה ומשפר את הביצועים, אבל יכול להיות שיהיה צורך להוסיף כללי שמירה כדי למנוע את הסרת הקוד הנדרש.
|