زمان راه اندازی اپلیکیشن

کاربران انتظار دارند برنامه ها سریع بارگذاری شوند و پاسخگو باشند. اپلیکیشنی با زمان شروع آهسته این انتظار را برآورده نمی کند و می تواند کاربران را ناامید کند. این نوع تجربه ضعیف می تواند باعث شود که کاربر به برنامه شما در فروشگاه Play رتبه ضعیفی بدهد یا حتی برنامه شما را به کلی رها کند.

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

وضعیت های مختلف راه اندازی اپلیکیشن را درک کنید

راه اندازی برنامه می تواند در یکی از سه حالت انجام شود: شروع سرد، شروع گرم یا شروع گرم. هر حالت بر مدت زمانی که طول می کشد تا برنامه شما برای کاربر قابل مشاهده شود، تأثیر می گذارد. در یک شروع سرد، برنامه شما از ابتدا شروع می شود. در سایر حالت ها، سیستم باید برنامه در حال اجرا را از پس زمینه به پیش زمینه بیاورد.

توصیه می کنیم همیشه بر اساس فرض شروع سرد بهینه سازی کنید. انجام این کار می تواند عملکرد شروع گرم و گرم را نیز بهبود بخشد.

برای بهینه سازی برنامه خود برای راه اندازی سریع، درک آنچه در سطوح سیستم و برنامه اتفاق می افتد و نحوه تعامل آنها در هر یک از این حالت ها مفید است.

دو معیار مهم برای تعیین راه‌اندازی برنامه عبارتند از: زمان تا نمایش اولیه (TTID) و زمان ترسیم کامل (TTFD) . TTID زمانی است که طول می کشد تا اولین فریم نمایش داده شود و TTFD زمانی است که طول می کشد تا برنامه کاملاً تعاملی شود. هر دو به یک اندازه مهم هستند، زیرا TTID به کاربر این امکان را می دهد که بداند برنامه در حال بارگیری است، و TTFD زمانی است که برنامه واقعاً قابل استفاده است. اگر هر یک از اینها خیلی طولانی باشد، ممکن است کاربر حتی قبل از بارگیری کامل از برنامه شما خارج شود.

شروع سرد

شروع سرد به شروع یک برنامه از صفر اشاره دارد. این بدان معنی است که تا این شروع، فرآیند سیستم، فرآیند برنامه را ایجاد می کند. شروع سرد در مواردی مانند راه اندازی برنامه شما برای اولین بار از زمان بوت شدن دستگاه یا زمانی که سیستم برنامه را از بین برده است، اتفاق می افتد.

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

در ابتدای شروع سرد، سیستم دارای سه وظیفه زیر است:

  1. برنامه را بارگیری و راه اندازی کنید.
  2. بلافاصله پس از راه اندازی، یک پنجره شروع خالی برای برنامه نمایش دهید.
  3. فرآیند برنامه را ایجاد کنید.

به محض اینکه سیستم فرآیند برنامه را ایجاد کرد، فرآیند برنامه مسئول مراحل بعدی است:

  1. شی برنامه را ایجاد کنید.
  2. تاپیک اصلی را راه اندازی کنید.
  3. فعالیت اصلی را ایجاد کنید.
  4. نماها را باد کنید.
  5. صفحه نمایش را چیدمان کنید.
  6. قرعه کشی اولیه را انجام دهید.

هنگامی که فرآیند برنامه اولین قرعه کشی را کامل کرد، فرآیند سیستم پنجره پس زمینه نمایش داده شده را تعویض می کند و آن را با فعالیت اصلی جایگزین می کند. در این مرحله، کاربر می تواند شروع به استفاده از برنامه کند.

شکل 1 نشان می دهد که چگونه پردازش های سیستم و برنامه بین یکدیگر کار می کنند.

شکل 1. یک نمایش بصری از بخش های مهم راه اندازی یک برنامه سرد.

مشکلات عملکرد ممکن است در حین ایجاد برنامه و ایجاد فعالیت ایجاد شود.

ایجاد اپلیکیشن

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

اگر Application.onCreate() را در برنامه خود نادیده بگیرید، سیستم متد onCreate() را در شی برنامه شما فراخوانی می کند. پس از آن، برنامه رشته اصلی را ایجاد می‌کند که به عنوان رشته رابط کاربری نیز شناخته می‌شود و به آن وظیفه ایجاد فعالیت اصلی شما را می‌دهد.

از این نقطه، فرآیندهای سطح سیستم و برنامه مطابق با مراحل چرخه حیات برنامه پیش می‌روند.

ایجاد فعالیت

پس از اینکه فرآیند برنامه فعالیت شما را ایجاد کرد، اکتیویتی عملیات زیر را انجام می دهد:

  1. مقادیر را اولیه می کند.
  2. سازنده ها را فرا می خواند.
  3. متد callback را فراخوانی می کند، مانند Activity.onCreate() متناسب با وضعیت چرخه حیات فعلی فعالیت.

به طور معمول، متد onCreate() بیشترین تأثیر را بر زمان بارگذاری دارد، زیرا کار را با بالاترین سربار انجام می‌دهد: بارگذاری و افزایش نماها و مقداردهی اولیه اشیاء مورد نیاز برای اجرای فعالیت.

شروع گرم

شروع گرم شامل زیرمجموعه ای از عملیات است که در طول شروع سرد انجام می شود. در عین حال، بیش از یک شروع داغ نشان دهنده سربار است. حالت های بالقوه زیادی وجود دارد که می توان آنها را شروع گرم در نظر گرفت، مانند موارد زیر:

  • کاربر از برنامه شما عقب نشینی می کند اما سپس آن را دوباره راه اندازی می کند. این فرآیند ممکن است به اجرای خود ادامه دهد، اما برنامه باید با استفاده از فراخوانی به onCreate() فعالیت را از ابتدا بازآفرینی کند.

  • سیستم برنامه شما را از حافظه خارج می کند و سپس کاربر آن را دوباره راه اندازی می کند. فرآیند و اکتیویتی نیاز به راه‌اندازی مجدد دارند، اما این وظیفه می‌تواند تا حدودی از بسته حالت ذخیره‌شده نمونه که به onCreate() منتقل می‌شود، سود ببرد.

شروع داغ

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

با این حال، اگر مقداری از حافظه در پاسخ به رویدادهای برش حافظه، مانند onTrimMemory() پاک شود، این اشیا باید در پاسخ به رویداد شروع داغ دوباره ایجاد شوند.

شروع گرم همان رفتار روی صفحه را نشان می دهد که سناریوی شروع سرد است. فرآیند سیستم یک صفحه خالی نمایش می دهد تا زمانی که برنامه رندر فعالیت را تمام کند.

شکل 2. نموداری با حالت های مختلف راه اندازی و فرآیندهای مربوط به آنها، که هر حالت از اولین فریم ترسیم شده شروع می شود.

نحوه شناسایی راه اندازی اپلیکیشن در Perfetto

برای رفع اشکال مشکلات راه‌اندازی برنامه، تعیین اینکه دقیقاً چه چیزی در مرحله راه‌اندازی برنامه گنجانده شده است، مفید است. برای شناسایی کل مرحله راه‌اندازی اپلیکیشن در Perfetto ، این مراحل را دنبال کنید:

  1. در Perfetto، ردیف را با متریک مشتق شده از Startups App Android پیدا کنید. اگر آن را نمی‌بینید، با استفاده از برنامه ردیابی سیستم روی دستگاه، ردیابی بگیرید.

    شکل 3. استارتاپ های برنامه اندروید برش متریک را در Perfetto مشتق کرده اند.
  2. بر روی برش مرتبط کلیک کرده و m را فشار دهید تا برش انتخاب شود. براکت ها در اطراف برش ظاهر می شوند و نشان می دهند که چقدر طول کشیده است. مدت زمان نیز در برگه انتخاب فعلی نشان داده شده است.

  3. با کلیک بر روی آیکون پین که با نگه داشتن نشانگر روی ردیف قابل مشاهده است، ردیف Startups App Android را پین کنید.

  4. به ردیف برنامه مورد نظر بروید و روی اولین سلول کلیک کنید تا ردیف گسترش یابد.

  5. با فشار دادن w روی رشته اصلی، معمولاً در بالا، بزرگنمایی کنید (به ترتیب s، a، d را فشار دهید، به سمت چپ حرکت کنید و به راست حرکت کنید).

    شکل 4. راه‌اندازی برنامه Android برش متریک را در کنار رشته اصلی برنامه به دست آورده است.
  6. برش معیارهای مشتق شده، دیدن اینکه دقیقاً چه چیزی در راه اندازی برنامه گنجانده شده است را آسان تر می کند، بنابراین می توانید با جزئیات بیشتر به اشکال زدایی ادامه دهید.

از معیارها برای بازرسی و بهبود استارت آپ ها استفاده کنید

برای تشخیص درست عملکرد زمان راه‌اندازی، می‌توانید معیارهایی را ردیابی کنید که نشان می‌دهد چقدر طول می‌کشد تا برنامه شما شروع به کار کند. اندروید چندین راه برای نشان دادن مشکل برنامه شما ارائه می دهد و به شما در تشخیص آن کمک می کند. Android vitals می تواند به شما هشدار دهد که مشکلی در حال رخ دادن است و ابزارهای تشخیصی می توانند به شما در تشخیص مشکل کمک کنند.

مزایای استفاده از معیارهای راه اندازی

Android از معیارهای زمان تا نمایش اولیه (TTID) و زمان تا نمایش کامل (TTFD) برای بهینه سازی راه اندازی برنامه های سرد و گرم استفاده می کند. Android Runtime (ART) از داده‌های این معیارها برای پیش‌کامپایل مؤثر کد برای بهینه‌سازی راه‌اندازی‌های آینده استفاده می‌کند.

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

حیاتی اندروید

Android vitals می تواند با هشدار دادن به شما در کنسول Play زمانی که زمان راه اندازی برنامه شما بیش از حد است، به بهبود عملکرد برنامه شما کمک کند.

Android vitals زمان های راه اندازی زیر را برای برنامه شما بیش از حد در نظر می گیرد:

  • راه اندازی سرد 5 ثانیه یا بیشتر طول می کشد.
  • راه اندازی گرم 2 ثانیه یا بیشتر طول می کشد.
  • راه اندازی داغ 1.5 ثانیه یا بیشتر طول می کشد.

Android vitals از متریک زمان تا نمایش اولیه (TTID) استفاده می کند. برای اطلاعات در مورد نحوه جمع‌آوری داده‌های حیاتی Android توسط Google Play، به مستندات Play Console مراجعه کنید.

زمان تا نمایش اولیه

زمان تا نمایش اولیه (TTID) زمانی است که برای نمایش اولین فریم رابط کاربری برنامه نیاز است. این متریک مدت زمانی را که طول می‌کشد تا یک برنامه اولین فریم خود را تولید کند، از جمله راه‌اندازی فرآیند در هنگام شروع سرد، ایجاد فعالیت در هنگام شروع سرد یا گرم و نمایش اولین فریم را اندازه‌گیری می‌کند. پایین نگه داشتن TTID برنامه به بهبود تجربه کاربری کمک می کند و به کاربران اجازه می دهد برنامه شما را به سرعت اجرا کنند. TTID به طور خودکار برای هر برنامه توسط چارچوب Android گزارش می شود. هنگام بهینه‌سازی برای راه‌اندازی برنامه، توصیه می‌کنیم reportFullyDrawn برای دریافت اطلاعات تا TTFD پیاده‌سازی کنید.

TTID به عنوان یک مقدار زمانی اندازه گیری می شود که کل زمان سپری شده را نشان می دهد که شامل توالی رویدادهای زیر است:

  • راه اندازی فرآیند.
  • مقداردهی اولیه اشیا
  • ایجاد و مقداردهی اولیه فعالیت
  • باد کردن طرح.
  • کشیدن برنامه برای اولین بار.

TTID را بازیابی کنید

برای پیدا کردن TTID، در ابزار خط فرمان Logcat یک خط خروجی حاوی مقداری به نام Displayed جستجو کنید. این مقدار TTID است و شبیه مثال زیر است که در آن TTID 3s534ms است:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

برای یافتن TTID در اندروید استودیو، فیلترها را در نمای Logcat خود از منوی کشویی فیلتر غیرفعال کنید و سپس همانطور که در شکل 5 نشان داده شده است، زمان Displayed را پیدا کنید. غیرفعال کردن فیلترها ضروری است زیرا سرور سیستم، نه خود برنامه، سرویس می‌دهد. این گزارش

شکل 5. فیلترهای غیرفعال و مقدار Displayed در logcat.

معیار Displayed در خروجی Logcat لزوماً مدت زمان بارگیری و نمایش همه منابع را نشان نمی دهد. منابعی را که در فایل طرح بندی ارجاع نشده اند یا برنامه به عنوان بخشی از مقداردهی اولیه شی ایجاد می کند، حذف می کند. این منابع را مستثنی می کند زیرا بارگیری آنها یک فرآیند درون خطی است و نمایش اولیه برنامه را مسدود نمی کند.

گاهی اوقات خط Displayed در خروجی Logcat حاوی یک فیلد اضافی برای کل زمان است. به عنوان مثال:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)

در این حالت اولین اندازه گیری فقط برای فعالیتی است که ابتدا ترسیم شده است. اندازه‌گیری زمان total از شروع فرآیند برنامه شروع می‌شود و می‌تواند شامل فعالیت دیگری باشد که ابتدا شروع شده است اما چیزی را روی صفحه نمایش نمی‌دهد. اندازه‌گیری زمان total فقط زمانی نشان داده می‌شود که بین زمان فعالیت واحد و کل زمان راه‌اندازی تفاوت وجود داشته باشد.

توصیه می‌کنیم از Logcat در Android Studio استفاده کنید، اما اگر از Android Studio استفاده نمی‌کنید، می‌توانید TTID را با اجرای برنامه خود با دستور adb shell activity manager اندازه‌گیری کنید. در اینجا یک مثال است:

adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN

متریک Displayed مانند قبل در خروجی Logcat ظاهر می شود. پنجره ترمینال شما موارد زیر را نمایش می دهد:

Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete

آرگومان های -c و -a اختیاری هستند و به شما اجازه می دهند <category> و <action> را مشخص کنید.

زمان نمایش کامل

زمان نمایش کامل (TTFD) زمانی است که طول می کشد تا یک برنامه برای کاربر تعاملی شود. زمان نمایش اولین فریم رابط کاربری برنامه و همچنین محتوایی که پس از نمایش فریم اولیه به صورت ناهمزمان بارگذاری می شود، گزارش می شود. به طور کلی، این محتوای اصلی است که از شبکه یا دیسک بارگذاری شده است، همانطور که توسط برنامه گزارش شده است. به عبارت دیگر، TTFD شامل TTID و همچنین مدت زمانی است که طول می کشد تا برنامه قابل استفاده باشد. پایین نگه داشتن TTFD برنامه به بهبود تجربه کاربری کمک می کند و به کاربران اجازه می دهد تا به سرعت با برنامه شما تعامل داشته باشند.

هنگامی که Choreographer متد onDraw() فعالیت را فراخوانی می‌کند، سیستم TTID را تعیین می‌کند، و زمانی که می‌داند برای اولین بار آن را فراخوانی می‌کند. با این حال، سیستم نمی‌داند چه زمانی باید TTFD را تعیین کند زیرا هر برنامه متفاوتی رفتار می‌کند. برای تعیین TTFD، برنامه باید زمانی که سیستم به حالت کاملا ترسیم شده رسید به سیستم سیگنال بدهد.

TTFD را بازیابی کنید

برای یافتن TTFD، با فراخوانی متد reportFullyDrawn() ComponentActivity وضعیت کاملا ترسیم شده را علامت بزنید. متد reportFullyDrawn زمانی گزارش می‌دهد که برنامه به طور کامل ترسیم شده و در حالت قابل استفاده باشد. TTFD زمان سپری شده از زمانی است که سیستم قصد راه اندازی برنامه را دریافت می کند تا زمانی که reportFullyDrawn() فراخوانی می شود. اگر reportFullyDrawn() فراخوانی نکنید، هیچ مقدار TTFD گزارش نمی شود.

برای اندازه گیری TTFD، پس از رسم کامل UI و تمام داده ها، reportFullyDrawn() را فراخوانی کنید. قبل از اینکه پنجره اولین فعالیت برای اولین بار ترسیم شود و به عنوان اندازه گیری شده توسط سیستم نمایش داده شود reportFullyDrawn() فراخوانی نکنید، زیرا در این صورت سیستم زمان اندازه گیری سیستم را گزارش می کند. به عبارت دیگر، اگر قبل از اینکه سیستم TTID را شناسایی کند، reportFullyDrawn() را فراخوانی کنید، سیستم TTID و TTFD را به عنوان یک مقدار گزارش می‌کند و این مقدار مقدار TTID است.

هنگامی که از reportFullyDrawn() استفاده می کنید، Logcat خروجی مانند مثال زیر را نمایش می دهد که در آن TTFD 1s54ms است:

system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms

خروجی Logcat گاهی اوقات شامل یک زمان total می شود، همانطور که در زمان تا نمایش اولیه بحث شده است.

اگر زمان نمایش شما کندتر از آنچه می خواهید است، می توانید سعی کنید گلوگاه ها را در فرآیند راه اندازی شناسایی کنید.

شما می توانید از reportFullyDrawn() برای علامت دادن به حالت کاملاً ترسیم شده در موارد اساسی که از رسیدن به حالت کاملاً ترسیم شده آگاه هستید استفاده کنید. با این حال، در مواردی که رشته‌های پس‌زمینه باید کار پس‌زمینه را قبل از رسیدن به حالت کاملاً ترسیم شده کامل کنند، برای اندازه‌گیری دقیق‌تر TTFD باید reportFullyDrawn() را به تأخیر بیندازید. برای یادگیری نحوه به تاخیر انداختن reportFullyDrawn() ، بخش زیر را ببینید.

بهبود دقت زمان‌بندی راه‌اندازی

اگر برنامه شما در حال بارگیری تنبل است و صفحه نمایش اولیه شامل همه منابع نمی شود، مانند زمانی که برنامه شما تصاویر را از شبکه واکشی می کند، ممکن است بخواهید تماس با reportFullyDrawn تا زمانی که برنامه قابل استفاده شود به تعویق بیندازید تا بتوانید لیست را اضافه کنید. جمعیت به عنوان بخشی از زمان بندی معیار شما.

به عنوان مثال، اگر UI حاوی یک لیست پویا باشد، مانند یک RecyclerView یا لیست تنبل، این ممکن است با یک کار پس‌زمینه پر شود که پس از اولین ترسیم لیست و بنابراین، پس از علامت‌گذاری UI به‌عنوان کاملاً رسم شده تکمیل می‌شود. در چنین مواردی، جمعیت فهرست در معیار قرار نمی‌گیرد.

برای گنجاندن جمعیت لیست به عنوان بخشی از زمان بندی معیار خود، با استفاده از getFullyDrawnReporter() FullyDrawnReporter دریافت کنید و یک گزارشگر به آن در کد برنامه خود اضافه کنید. پس از اتمام کار پس‌زمینه پر کردن لیست، گزارشگر را رها کنید.

FullyDrawnReporter متد reportFullyDrawn() فراخوانی نمی کند تا زمانی که همه گزارشگران اضافه شده آزاد شوند. با افزودن یک گزارشگر تا تکمیل فرآیند پس‌زمینه، زمان‌بندی‌ها همچنین شامل مدت زمانی است که برای پر کردن لیست در داده‌های زمان‌بندی راه‌اندازی لازم است. این رفتار برنامه را برای کاربر تغییر نمی‌دهد، اما به داده‌های راه‌اندازی زمان‌بندی اجازه می‌دهد تا زمانی را که برای پر کردن فهرست نیاز است را شامل شود. reportFullyDrawn() فراخوانی نمی شود تا زمانی که همه وظایف بدون توجه به ترتیب تکمیل شوند.

مثال زیر نشان می‌دهد که چگونه می‌توانید چندین کار پس‌زمینه را به طور همزمان اجرا کنید و هر کدام گزارشگر خود را ثبت کنند:

کاتلین

class MainActivity : ComponentActivity() {

    sealed interface ActivityState {
        data object LOADING : ActivityState
        data object LOADED : ActivityState
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            var activityState by remember {
                mutableStateOf(ActivityState.LOADING as ActivityState)
            }
            fullyDrawnReporter.addOnReportDrawnListener {
                activityState = ActivityState.LOADED
            }
            ReportFullyDrawnTheme {
                when(activityState) {
                    is ActivityState.LOADING -> {
                        // Display the loading UI.
                    }
                    is ActivityState.LOADED -> {
                        // Display the full UI.
                    }
                }
            }
            SideEffect {
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
            }
        }
    }
}

جاوا

public class MainActivity extends ComponentActivity {
    private FullyDrawnReporter fullyDrawnReporter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        fullyDrawnReporter = getFullyDrawnReporter();
        fullyDrawnReporter.addOnReportDrawnListener(() -> {
            // Trigger the UI update.
            return Unit.INSTANCE;
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

               fullyDrawnReporter.removeReporter();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

                fullyDrawnReporter.removeReporter();
            }
        }).start();
    }
}

اگر برنامه شما از Jetpack Compose استفاده می‌کند، می‌توانید از APIهای زیر برای نشان دادن وضعیت کاملاً ترسیم شده استفاده کنید:

  • ReportDrawn : نشان می دهد که composable شما بلافاصله برای تعامل آماده است.
  • ReportDrawnWhen : یک گزاره مانند list.count > 0 را می گیرد تا نشان دهد که سازنده شما چه زمانی برای تعامل آماده است.
  • ReportDrawnAfter : یک روش تعلیق می گیرد که پس از تکمیل، نشان می دهد که composable شما برای تعامل آماده است.
تنگناها را شناسایی کنید

برای جستجوی گلوگاه ها، می توانید از پروفایل CPU Android Studio استفاده کنید. برای اطلاعات بیشتر، به بررسی فعالیت CPU با CPU Profiler مراجعه کنید.

همچنین می‌توانید از طریق ردیابی درون خطی در روش‌های onCreate() برنامه‌ها و فعالیت‌های خود، بینشی درباره تنگناهای احتمالی کسب کنید. برای آشنایی با ردیابی درون خطی، به مستندات مربوط به توابع Trace و نمای کلی ردیابی سیستم مراجعه کنید.

مسائل رایج را حل کنید

این بخش چندین موضوع را مورد بحث قرار می دهد که اغلب بر عملکرد راه اندازی برنامه تأثیر می گذارد. این مسائل عمدتاً مربوط به مقداردهی اولیه برنامه ها و اشیاء فعالیت و همچنین بارگذاری صفحه نمایش است.

مقداردهی اولیه برنامه سنگین

عملکرد راه‌اندازی ممکن است زمانی که کد شما روی شیء Application لغو می‌شود و کار سنگین یا منطق پیچیده را هنگام مقداردهی اولیه آن شی اجرا می‌کند، دچار مشکل می‌شود. برنامه شما ممکن است در هنگام راه‌اندازی وقت خود را تلف کند، اگر زیرکلاس‌های Application شما مقداردهی اولیه‌سازی‌هایی را انجام دهند که هنوز نیازی به انجام آن نیست.

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

چالش‌های دیگر در طول راه‌اندازی برنامه شامل رویدادهای جمع‌آوری زباله‌هایی است که تأثیرگذار یا متعدد هستند، یا ورودی/خروجی دیسک همزمان با مقداردهی اولیه اتفاق می‌افتد، که روند اولیه‌سازی را بیشتر مسدود می‌کند. جمع آوری زباله به ویژه در مورد زمان اجرا Dalvik مورد توجه است. Android Runtime (ART) جمع آوری زباله را به طور همزمان انجام می دهد و تأثیر آن عملیات را به حداقل می رساند.

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

برای تشخیص مشکل می توانید از روش ردیابی یا ردیابی درون خطی استفاده کنید.

ردیابی روش

اجرای CPU Profiler نشان می دهد که متد callApplicationOnCreate() در نهایت متد com.example.customApplication.onCreate شما را فراخوانی می کند. اگر ابزار نشان می‌دهد که اجرای این روش‌ها زمان زیادی می‌برد، بیشتر کاوش کنید تا ببینید چه کاری در آنجا انجام می‌شود.

ردیابی درون خطی

از ردیابی درون خطی برای بررسی مقصران احتمالی استفاده کنید، از جمله موارد زیر:

  • تابع onCreate() اولیه برنامه شما.
  • هر شی سینگلتون جهانی که برنامه شما مقداردهی اولیه می کند.
  • هر ورودی/خروجی دیسک، deserialization، یا حلقه های محکمی که ممکن است در طول گلوگاه رخ دهد.

راه حل های مشکل

چه مشکل از مقداردهی اولیه غیرضروری باشد و چه با ورودی/خروجی دیسک، راه حل اولیه سازی تنبل است. به عبارت دیگر، فقط اشیایی را که فورا مورد نیاز هستند مقداردهی اولیه کنید. به جای ایجاد اشیاء ثابت سراسری، به الگوی تک‌تنه‌ای بروید که در آن برنامه فقط اولین باری که به آن‌ها نیاز دارد، اشیاء را مقداردهی اولیه می‌کند.

همچنین، استفاده از یک چارچوب تزریق وابستگی مانند Hilt را در نظر بگیرید که در هنگام تزریق برای اولین بار، اشیا و وابستگی ها را ایجاد می کند.

اگر برنامه شما از ارائه دهندگان محتوا برای مقداردهی اولیه اجزای برنامه در هنگام راه اندازی استفاده می کند، به جای آن از کتابخانه App Startup استفاده کنید.

مقداردهی اولیه فعالیت سنگین

ایجاد فعالیت اغلب مستلزم کارهای سنگین زیادی است. اغلب، فرصت هایی برای بهینه سازی این کار برای دستیابی به بهبود عملکرد وجود دارد. چنین مسائل رایج شامل موارد زیر است:

  • باد کردن چیدمان های بزرگ یا پیچیده.
  • مسدود کردن طراحی صفحه روی دیسک یا ورودی/خروجی شبکه.
  • بارگذاری و رمزگشایی بیت مپ ها.
  • Rasterizing اشیاء VectorDrawable .
  • راه اندازی زیرسیستم های دیگر فعالیت.

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

در این مورد نیز هر دو روش ردیابی و ردیابی درون خطی می توانند مفید باشند.

ردیابی روش

هنگام استفاده از CPU Profiler، به سازنده های زیرکلاس Application و متدهای com.example.customApplication.onCreate() برنامه خود توجه کنید.

اگر ابزار نشان می‌دهد که اجرای این روش‌ها زمان زیادی می‌برد، بیشتر کاوش کنید تا ببینید چه کاری در آنجا انجام می‌شود.

ردیابی درون خطی

از ردیابی درون خطی برای بررسی مقصران احتمالی استفاده کنید، از جمله موارد زیر:

  • تابع onCreate() اولیه برنامه شما.
  • هر شیء تکی سراسری که مقداردهی اولیه می کند.
  • هر ورودی/خروجی دیسک، deserialization، یا حلقه های محکمی که ممکن است در طول گلوگاه رخ دهد.

راه حل های مشکل

تنگناهای بالقوه زیادی وجود دارد، اما دو مشکل و راه حل رایج به شرح زیر است:

  • هر چه سلسله مراتب نمایش شما بزرگتر باشد، برنامه زمان بیشتری را برای افزایش آن صرف می کند. دو مرحله ای که می توانید برای رفع این مشکل انجام دهید به شرح زیر است:
    • سلسله مراتب نمای خود را با کاهش طرح‌بندی‌های اضافی یا تودرتو صاف کنید.
    • بخش‌هایی از رابط کاربری را که نیازی به نمایان شدن در هنگام راه‌اندازی ندارند، پر نکنید. در عوض، از یک شی ViewStub به عنوان یک مکان نگهدار برای زیر سلسله مراتبی استفاده کنید که برنامه بتواند در زمان مناسب تری آن را افزایش دهد.
  • داشتن تمام مقداردهی اولیه منابع روی رشته اصلی نیز می تواند سرعت راه اندازی را کند کند. می توانید به این صورت به این موضوع بپردازید:
    • تمام مقداردهی اولیه منابع را جابه‌جا کنید تا برنامه بتواند آن را با تنبلی در رشته‌ای متفاوت انجام دهد.
    • به برنامه اجازه دهید نماهای شما را بارگیری و نمایش دهد و بعداً ویژگی های بصری را که به بیت مپ و منابع دیگر وابسته هستند به روز کنید.

صفحه نمایش اسپلش سفارشی

اگر قبلاً از یکی از روش‌های زیر برای پیاده‌سازی صفحه نمایش سفارشی در Android 11 (سطح API 30) یا قبل‌تر استفاده کرده‌اید، ممکن است زمان بیشتری در هنگام راه‌اندازی اضافه شود:

  • با استفاده از ویژگی windowDisablePreview theme برای خاموش کردن صفحه خالی اولیه ترسیم شده توسط سیستم در حین راه اندازی.
  • استفاده از یک Activity اختصاصی

با شروع Android 12، مهاجرت به SplashScreen API ضروری است. این API زمان راه‌اندازی سریع‌تری را فعال می‌کند و به شما امکان می‌دهد صفحه نمایش خود را به روش‌های زیر تغییر دهید:

علاوه بر این، کتابخانه compat از SplashScreen API پشتیبانی می کند تا سازگاری با عقب را فعال کند و ظاهر و احساسی ثابت برای نمایش صفحه نمایش اسپلش در تمام نسخه های اندروید ایجاد کند.

برای جزئیات به راهنمای انتقال صفحه Splash مراجعه کنید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}