تشخیص مشکلات پایداری

اگر با مشکلات عملکردی مواجه هستید که ناشی از بازترکیب غیرضروری یا بیش‌ازحد است، باید پایداری برنامه‌تان را اشکال‌زدایی کنید. این راهنما چند روش برای انجام این کار را شرح می‌دهد.

بازرس چیدمان

«بازرس چیدمان» در Android Studio به شما امکان می‌دهد ببینید کدام ترکیب‌شدنی‌ها در برنامه‌تان درحال ترکیب‌بندی مجدد هستند. این ابزار تعداد دفعاتی را که Compose یک مؤلفه را ترکیب‌بندی مجدد کرده یا از آن رد شده است نمایش می‌دهد.

تعداد بازترکیب‌ها و پرش‌ها در «بازرس چیدمان»

گزارش‌های کامپایلر Compose

کامپایلر Compose می‌تواند نتایج استنتاج پایداری خود را برای بازرسی خروجی دهد. بااستفاده از این خروجی، می‌توانید تعیین کنید کدام‌یک از ترکیب‌پذیرهایتان قابل‌ردشدن هستند و کدام‌یک نیستند. زیربخش‌های زیر نحوه استفاده از این گزارش‌ها را خلاصه می‌کنند، اما برای اطلاعات دقیق‌تر، به اسناد فنی مراجعه کنید.

راه‌اندازی

گزارش‌های کامپایلر Compose به‌طور پیش‌فرض فعال نیستند. می‌توانید آن‌ها را با پرچم کامپایلر فعال کنید. راه‌اندازی دقیق بسته به پروژه شما متفاوت است، اما برای پروژه‌هایی که از افزونه Compose compiler gradle استفاده می‌کنند، می‌توانید موارد زیر را در فایل build.gradle هر ماژول اضافه کنید.

  android { ... }

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

گزارش‌های کامپایلر Compose اکنون هنگام ساختن پروژه‌تان تولید خواهد شد.

برونداد نمونه

reportsDestination سه فایل خروجی می‌دهد. در زیر نمونه‌هایی از خروجی‌های JetSnack آورده شده است.

  • <modulename>-classes.txt: گزارشی درباره پایداری کلاس‌ها در این واحد. نمونه.
  • <modulename>-composables.txt: گزارشی درباره اینکه ترکیب‌پذیرها در واحد چقدر قابل‌راه‌اندازی مجدد و قابل‌رد شدن هستند. نمونه.
  • <modulename>-composables.csv:نسخه CSV از گزارش composables که می‌توانید آن را به صفحه‌گسترده وارد کنید یا بااستفاده از دستورگان پردازش کنید. نمونه

گزارش Composables

فایل 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 با stable علامت‌گذاری شده است، بنابراین Compose هر پارامتر را بااستفاده از برابری ساختاری (Object.equals()) مقایسه می‌کند. درحالی‌که پارامترهای stable برای مقادیر اولیه و کلاس‌های داده کوچک و مسطح با بررسی‌های .equals() ارزان ایده‌آل هستند، اجبار مدل‌های نگه‌دارنده مجموعه (مانند SnackCollection که List<Snack> را دربرمی‌گیرد) به stable بودن باعث می‌شود Compose .equals() را برای هر مورد در هر بازترکیب فراخوانی کند. وقتی حالت پرش قوی فعال باشد، نگه‌داشتن مدل‌هایی که مجموعه‌ها را نگه می‌دارند unstable ترجیح داده می‌شود تا Compose آن‌ها را بااستفاده از برابری نمونه (===) مقایسه کند.

یا نمونه دیگری را درنظر بگیرید که با غیرفعال بودن حالت پرش قوی تولید شده است:

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
)

وقتی حالت پرش قوی غیرفعال است (قبل‌از Kotlin 2.0.20)، HighlightedSnacks composable قابل‌پرش نیست—Compose هرگز درطول بازترکیب از آن نمی‌پرد، حتی اگر هیچ‌کدام از پارامترهای آن تغییر نکرده باشد، به‌دلیل unstable پارامتر snacks.

با فعال بودن حالت پرش قوی (پیش‌فرض در Kotlin 2.0.20 و بالاتر)، HighlightedSnacks به‌عنوان skippable علامت‌گذاری می‌شود و Compose پارامتر unstable snacks را بااستفاده از برابری نمونه (===) مقایسه می‌کند. درنتیجه، Compose از HighlightedSnacks می‌پرد اگر همان مرجع List ارسال شود و فقط اگر نمونه List جدیدی اختصاص داده شود، آن را بازترکیب می‌کند.

گزارش کلاس‌ها

فایل 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 را به‌عنوان ناپایدار علامت‌گذاری می‌کند.