אבחון בעיות ביציבות

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

כלי לבדיקת פריסות

הכלי Layout Inspector ב-Android Studio מאפשר לראות אילו פונקציות Composable עוברות קומפוזיציה מחדש באפליקציה. הוא מציג את מספר הפעמים שבהן Compose ביצע קומפוזיציה מחדש של רכיב או דילג עליו.

המספרים של הרכבה מחדש ודילוגים בכלי לבדיקת פריסות

כתיבת דוחות של קומפיילר

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

הגדרה

דוחות של מהדר Compose לא מופעלים כברירת מחדל. אפשר להפעיל אותן באמצעות דגל של קומפיילר. ההגדרה המדויקת משתנה בהתאם לפרויקט, אבל בפרויקטים שמשתמשים ב-Compose compiler gradle plugin אפשר להוסיף את הקוד הבא לקובץ build.gradle של כל מודול.

  android { ... }

  composeCompiler {
    reportsDestination = layout.buildDirectory.dir("compose_compiler")
    metricsDestination = layout.buildDirectory.dir("compose_compiler")
  }

דוחות של קומפיילר Compose ייווצרו עכשיו כשמבצעים build לפרויקט.

פלט לדוגמה

הפלט של reportsDestination הוא שלושה קבצים. הדוגמאות הבאות הן של פלט מ-JetSnack.

  • <modulename>-classes.txt: דוח על היציבות של השיעורים במודול הזה. דוגמה.
  • <modulename>-composables.txt: דוח על מידת האפשרות להפעלה מחדש ודילוג על רכיבי ה-Composable במודול. דוגמה.
  • <modulename>-composables.csv: גרסת CSV של דוח הרכיבים הניתנים להרכבה שאפשר לייבא לגיליון אלקטרוני או לעבד באמצעות סקריפט. דוגמה

דוח על רכיבים שאפשר להרכיב

בקובץ composables.txt מפורטות כל הפונקציות שאפשר להרכיב עבור המודול הנתון, כולל היציבות של הפרמטרים שלהן, והאם אפשר להפעיל אותן מחדש או לדלג עליהן. הנה דוגמה היפותטית מתוך JetSnack:

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
  stable snackCollection: SnackCollection
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
  stable index: Int = @static 0
  stable highlight: Boolean = @static true
)

אפשר להפעיל מחדש את רכיב ה-SnackCollection הזה, לדלג עליו והוא יציב. בדרך כלל עדיף לעשות את זה, אבל זה לא חובה.

לעומת זאת, נבחן דוגמה אחרת.

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  unstable snacks: List<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

אי אפשר לדלג על רכיב ה-HighlightedSnacks. ההודעה אף פעם לא נמחקת במהלך הכתיבה מחדש. ההודעה הזו מופיעה גם אם אף אחד מהפרמטרים לא השתנה. הסיבה לכך היא הפרמטר unstable, snacks.

הדוח 'כיתות'

הקובץ classes.txt מכיל דוח דומה על הכיתות במודול הנתון. קטע הקוד הבא הוא הפלט של המחלקה Snack:

unstable class Snack {
  stable val id: Long
  stable val name: String
  stable val imageUrl: String
  stable val price: Long
  stable val tagline: String
  unstable val tags: Set<String>
  <runtime stability> = Unstable
}

לעיון, זו ההגדרה של Snack:

data class Snack(
    val id: Long,
    val name: String,
    val imageUrl: String,
    val price: Long,
    val tagline: String = "",
    val tags: Set<String> = emptySet()
)

הקומפיילר של Compose סימן את Snack כלא יציב. הסיבה לכך היא שהסוג של הפרמטר tags הוא Set<String>. זהו סוג נתונים שלא ניתן לשינוי, כי הוא לא MutableSet. עם זאת, מחלקות איסוף רגילות כמו Set, List ו-Map הן בסופו של דבר ממשקים. לכן, יכול להיות שההטמעה הבסיסית עדיין ניתנת לשינוי.

לדוגמה, אפשר לכתוב val set: Set<String> = mutableSetOf("foo"). המשתנה הוא קבוע והסוג המוצהר שלו לא ניתן לשינוי, אבל ההטמעה שלו עדיין ניתנת לשינוי. קומפיילר ה-Compose לא יכול להיות בטוח באי-השתנות של המחלקה הזו כי הוא רואה רק את הסוג המוצהר. לכן, המערכת מסמנת את tags כלא יציב.