Strong Skipping הוא מצב שזמין במהדר של Compose. כשהיא מופעלת, היא משנה את התנהגות המהדר בשתי דרכים:
- רכיבים מורכבים עם פרמטרים לא יציבים הופכים לניתנים לדילוג
- פונקציות Lambda עם צילום לא יציב נשמרות
הפעלת מצב דילוג חזק
כדי להפעיל דילוג חזק על מודול Gradle בגרסה קודמת, צריך לכלול את האפשרות הבאה בבלוק composeCompiler
של הגדרת Gradle:
android { ... }
composeCompiler {
enableStrongSkippingMode = true
}
אפשרות דילוג קומפוזיציונית
מצב דילוג חזק מרגיע חלק מכללי היציבות שבדרך כלל מחילים מהדר (compiler) בנושא דילוגים ופונקציות קומפוזביליות. כברירת מחדל, המהדר לכתיבה מסמן פונקציה קומפוזבילית כפונקציה שניתן לדלג עליה אם לכל הארגומנטים יש ערכים יציבים. מצב דילוג חזק משנה את זה.
כשהאפשרות 'דילוג חזק' מופעלת, אפשר לדלג על כל הפונקציות הניתנות לקיפול וניתן להפעיל אותן מחדש. הדבר רלוונטי גם אם יש להם פרמטרים לא יציבים וגם אם אין להם. לא ניתן לדלג על פונקציות קומפוזביליות שלא ניתנות להפעלה מחדש.
מתי כדאי לדלג
כדי לקבוע אם לדלג על תוכן קומפוזבילי במהלך הרכבה מחדש, התכונה 'פיתוח נייטיב' משווה את הערך של כל פרמטר לערכים הקודמים שלו. סוג ההשוואה תלוי ביציבות של הפרמטר.
- המערכת משווה בין פרמטרים לא יציבים באמצעות 'שוויון בין מכונות' (
===
) - השוואה של פרמטרים יציבים מתבצעת באמצעות בדיקת שוויון בין אובייקטים (
Object.equals()
)
אם כל הפרמטרים עומדים בדרישות האלה, התכונה 'כתיבה' תדלג על התוכן הקומפוזבילי במהלך ההרכבה מחדש.
כדאי לשקול תוכן קומפוזבילי כדי להפסיק להשתמש בדילוג חזק. כלומר, יכול להיות שתרצו
להזמין תוכן קומפוזבילי שניתן להפעיל מחדש אבל לא ניתן לדלג עליו. במקרה כזה, צריך להשתמש בהערה @NonSkippableComposable
.
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}
הוספת הערות לכיתות ככיתות יציבות
אם רוצים אובייקט שמשתמש בשוויון אובייקטים במקום בשוויון מופעים, ממשיכים להוסיף הערה לכיתה הנתונה באמצעות @Stable
.
דוגמה למקרה שבו יכול להיות שתצטרכו לעשות זאת היא כשאתם צופים ברשימת אובייקטים שלמה. מקורות נתונים כמו Room מקצים אובייקטים חדשים לכל פריט ברשימה בכל פעם שאחד מהם משתנה.
שימוש בזיכרון לטווח ארוך (memoization) ב-Lambda
מצב דילוג חזק מאפשר גם יותר זיכרונות של lambdas בתוך תכנים קומפוזביליים. כשהאפשרות 'דילוג חזק' מופעלת, כל פונקציית lambda בתוך פונקציה שניתנת ליצירה תישמר באופן אוטומטי.
דוגמאות
כדי להשיג שינון של lambdas בתוך תכנים קומפוזביליים כשמשתמשים בדילוג חזק, המהדר אוף את ה-lambda עם קריאה ל-remember
. הוא מחובר לצילומי המסך של הלמבדה.
קחו לדוגמה מקרה שבו יש לכם lambda כמו בדוגמה הבאה:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = {
use(unstableObject)
use(stableObject)
}
}
כאשר דילוג חזק מופעל, המהדר זוכר את ה-lambda על ידי האריזה שלו בקריאה remember
:
@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
val lambda = remember(unstableObject, stableObject) {
{
use(unstableObject)
use(stableObject)
}
}
}
המפתחות פועלים לפי אותם כללי השוואה שפועלים על פונקציות שניתנות ליצירה. סביבת זמן הריצה משווה בין מפתחות לא יציבים באמצעות שוויון בין מכונות. הוא משווה בין מפתחות יציבים באמצעות שוויון אובייקטים.
זיכרונות והרכבה מחדש
האופטימיזציה הזו מגדילה באופן משמעותי את מספר הרכיבים הניתנים לשילוב שהזמן שפועל בסביבת זמן הריצה מדלג עליהם במהלך היצירה מחדש. בלי שימוש בזיכרון, סביר להניח שהזמן שבו יתבצע שיוך של פונקציית lambda חדשה לכל רכיב שאפשר לשלב עם פרמטר lambda במהלך הרכבת מחדש יהיה ארוך יותר. כתוצאה מכך, ל-lambda החדש יש פרמטרים שלא שווים להרכב הקודם. התוצאה היא הרכבה מחדש.
הימנעות מ-memoization
אם יש lambda שאתם לא רוצים לזכור, אפשר להשתמש בהערה @DontMemoize
.
val lambda = @DontMemoize {
...
}
גודל APK
כשמפעילים הידור, רכיבי Composable שניתן לדלג עליהם יוצרים יותר קוד מאשר רכיבי Composable שלא ניתן לדלג עליהם. כשהתכונה 'דילוג חזק' מופעלת, המהדר מסמן כמעט את כל התכנים הקומפוזביליים כתוכן שניתן לדלג עליו, ועוטף את כל פריטי ה-lambda ב-remember{...}
. לכן, הפעלת מצב דילוג חזק משפיעה במידה קטנה מאוד על גודל ה-APK של האפליקציה.
הפעלת דילוג חזק ב-Now In Android הגדילה את גודל ה-APK ב-4KB. ההבדל בגודל תלוי במידה רבה במספר הרכיבים הניתנים לשילוב שלא ניתן היה לדלג עליהם בעבר באפליקציה הנתונה, אבל הוא אמור להיות קטן יחסית.