מצב דילוג חזק

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

הפעלת מצב דילוג מהיר

כדי להפעיל דילוג חזק במודול Gradle, צריך לכלול את האפשרות הבאה הבלוק composeCompiler בהגדרות האישיות של Gradle:

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

אפשרות דילוג על קומפוזבילי

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

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

מתי כדאי לדלג

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

  • המערכת משווה בין פרמטרים לא יציבים באמצעות 'שוויון בין מכונות' (===)
  • המערכת משווה בין פרמטרים יציבים באמצעות שוויון האובייקטים (Object.equals())

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

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

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

הוספת הערות לכיתות כיציבות

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

זכירת Lambda

מצב דילוג חזק גם מאפשר זיכרון יותר של דמויות lambda בתוך תכנים קומפוזביליים. כאשר דילוג חזק מופעל, כל 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 החדש יש פרמטרים שלא שווים ל- את היצירה האחרונה. התוצאה היא הרכבה מחדש.

הימנעות מזיכרון

אם יש לך lambda שאתה לא רוצה לזכור, אפשר להשתמש ב@DontMemoize הערה.

val lambda = @DontMemoize {
    ...
}

גודל APK

בהידור, תכנים קומפוזביליים שניתן לדלג עליהם יוצרים יותר קוד שנוצר תכנים קומפוזביליים שאי אפשר לדלג עליהם. כאשר דילוג חזק מופעל, המהדר מסמן כמעט את כל התכנים הקומפוזביליים כמוצרים שניתן לדלג עליהם ועוטף את כל ה-lambdas remember{...} לכן, כשמפעילים את המצב של דילוג חזק, משפיעה על גודל ה-APK של האפליקציה.

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