کاربران انتظار دارند برنامهها سریع بارگذاری شوند و واکنشگرا باشند. برنامهای با زمان شروع کند این انتظار را برآورده نمیکند و میتواند کاربران را ناامید کند. این نوع تجربه ضعیف میتواند باعث شود کاربر به برنامه شما در فروشگاه Play امتیاز ضعیفی بدهد یا حتی برنامه شما را به طور کلی کنار بگذارد.
این صفحه اطلاعاتی را برای کمک به بهینهسازی زمان راهاندازی برنامه شما ارائه میدهد، از جمله مروری بر اجزای داخلی فرآیند راهاندازی، نحوهی نمایش عملکرد راهاندازی و برخی از مشکلات رایج زمان راهاندازی به همراه نکاتی در مورد چگونگی رسیدگی به آنها.
درک حالتهای مختلف شروع برنامه
اجرای برنامه میتواند در یکی از سه حالت زیر انجام شود: شروع سرد، شروع گرم یا شروع داغ. هر حالت بر مدت زمان قابل مشاهده شدن برنامه شما برای کاربر تأثیر میگذارد. در حالت شروع سرد، برنامه شما از ابتدا شروع میشود. در حالتهای دیگر، سیستم باید برنامه در حال اجرا را از پسزمینه به پیشزمینه بیاورد.
توصیه میکنیم همیشه بر اساس فرض استارت سرد، بهینهسازی را انجام دهید. انجام این کار میتواند عملکرد استارت گرم و داغ را نیز بهبود بخشد.
برای بهینهسازی برنامه خود برای راهاندازی سریع، درک آنچه در سطح سیستم و برنامه اتفاق میافتد و نحوه تعامل آنها در هر یک از این حالتها مفید است.
دو معیار مهم برای تعیین زمان شروع به کار برنامه ، زمان نمایش اولیه (TTID) و زمان نمایش کامل (TTFD) هستند. TTID مدت زمانی است که طول میکشد تا اولین فریم نمایش داده شود و TTFD مدت زمانی است که طول میکشد تا برنامه کاملاً تعاملی شود. هر دو به یک اندازه مهم هستند، زیرا TTID به کاربر اطلاع میدهد که برنامه در حال بارگیری است و TTFD زمانی است که برنامه واقعاً قابل استفاده است. اگر هر یک از این موارد خیلی طولانی باشد، ممکن است کاربر قبل از بارگیری کامل، از برنامه شما خارج شود.
استارت سرد
شروع سرد به شروع یک برنامه از ابتدا اشاره دارد. این بدان معناست که تا زمان شروع، فرآیند سیستم، فرآیند برنامه را ایجاد میکند. شروع سرد در مواردی مانند اجرای برنامه شما برای اولین بار از زمان بوت شدن دستگاه یا از زمانی که سیستم برنامه را از کار انداخته است، اتفاق میافتد.
این نوع شروع، بزرگترین چالش را برای به حداقل رساندن زمان راهاندازی ارائه میدهد، زیرا سیستم و برنامه نسبت به سایر حالتهای راهاندازی، کار بیشتری برای انجام دادن دارند.
در ابتدای شروع سرد، سیستم سه وظیفه زیر را بر عهده دارد:
- برنامه را بارگیری و اجرا کنید.
- بلافاصله پس از اجرا، یک پنجره شروع خالی برای برنامه نمایش داده میشود.
- فرآیند برنامه را ایجاد کنید.
به محض اینکه سیستم فرآیند برنامه را ایجاد کرد، فرآیند برنامه مسئول مراحل بعدی است:
- شیء app را ایجاد کنید.
- تاپیک اصلی رو راه اندازی کنید.
- فعالیت اصلی را ایجاد کنید.
- رابط کاربری را مقداردهی اولیه کنید.
- رابط کاربری را روی صفحه بکشید.
وقتی فرآیند برنامه اولین ترسیم را کامل میکند، فرآیند سیستم پنجره پسزمینه نمایش داده شده را عوض میکند و آن را با فعالیت اصلی جایگزین میکند. در این مرحله، کاربر میتواند شروع به استفاده از برنامه کند.
برای اطلاعات بیشتر در مورد مراحل طرحبندی در Compose، به مراحل Jetpack Compose مراجعه کنید.
مشکلات عملکردی میتوانند در طول ایجاد برنامه و ایجاد فعالیت میزبان ایجاد شوند.
ایجاد برنامه
وقتی برنامه شما اجرا میشود، پنجره شروع خالی روی صفحه باقی میماند تا زمانی که سیستم ترسیم برنامه را برای اولین بار تمام کند. در این مرحله، فرآیند سیستم پنجره شروع را با برنامه شما عوض میکند و به کاربر اجازه میدهد با برنامه تعامل داشته باشد.
اگر Application.onCreate در برنامه خود override کنید، سیستم متد onCreate را روی شیء برنامه شما فراخوانی میکند. پس از آن، برنامه، نخ اصلی، که به عنوان نخ UI نیز شناخته میشود، را ایجاد میکند و آن را موظف به ایجاد فعالیت میزبان برنامه شما میکند.
از این نقطه، فرآیندهای سطح سیستم و برنامه مطابق با مراحل چرخه حیات برنامه پیش میروند.
ایجاد فعالیت
پس از اینکه فرآیند برنامه، اکتیویتی شما را ایجاد کرد، اکتیویتی عملیات زیر را انجام میدهد:
- مقادیر را مقداردهی اولیه میکند.
- سازندهها را فراخوانی میکند.
- متد callback، مانند
Activity.onCreate، را متناسب با وضعیت چرخه حیات فعلی اکتیویتی فراخوانی میکند.
معمولاً متد onCreate بیشترین تأثیر را بر زمان بارگذاری دارد. در یک برنامه Jetpack Compose، سربار متد onCreate اغلب از ترکیب اولیه ناشی میشود. این اتفاق زمانی میافتد که برنامه شما setContent فراخوانی میکند و composableهای سطح بالای شما را فراخوانی میکند. یک سلسله مراتب رابط کاربری عمیق یا پیچیده، یا composableهایی که محاسبات سنگینی را در نخ اصلی انجام میدهند، میتوانند این زمان ترکیب را افزایش دهند.
شروع گرم
یک شروع گرم شامل زیرمجموعهای از عملیاتی است که در طول یک شروع سرد انجام میشوند. در عین حال، سربار بیشتری نسبت به یک شروع گرم نشان میدهد. حالتهای بالقوه زیادی وجود دارد که میتوان آنها را شروع گرم در نظر گرفت، مانند موارد زیر:
کاربر از برنامه شما خارج میشود اما سپس آن را دوباره اجرا میکند. این فرآیند ممکن است به اجرا ادامه دهد، اما برنامه باید با استفاده از فراخوانی
onCreateاکتیویتی را از ابتدا بازسازی کند.سیستم برنامه شما را از حافظه خارج میکند و سپس کاربر آن را دوباره اجرا میکند. فرآیند و فعالیت باید مجدداً راهاندازی شوند، اما این وظیفه میتواند تا حدودی از بسته وضعیت نمونه ذخیره شده که به
onCreateارسال میشود، بهرهمند شود.
شروع داغ
شروع داغ برنامه شما سربار کمتری نسبت به شروع سرد دارد. در شروع داغ، سیستم فعالیت میزبان برنامه شما را به پیشزمینه میآورد. اگر تمام رابط کاربری برنامه شما هنوز در حافظه مستقر باشد، برنامه میتواند از تکرار مقداردهی اولیه شیء، مقداردهی اولیه رابط کاربری و رندر جلوگیری کند.
با این حال، اگر مقداری از حافظه در پاسخ به رویدادهای اصلاح حافظه، مانند onTrimMemory ، پاک شود، این اشیاء باید در پاسخ به رویداد شروع سریع (hot start) دوباره ایجاد شوند.
یک شروع داغ، همان رفتار روی صفحه را مانند سناریوی شروع سرد نشان میدهد. فرآیند سیستم تا زمانی که برنامه رندر کردن فعالیت را تمام کند، یک صفحه خالی نمایش میدهد.

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

شکل ۲. برش متریک مشتق شده توسط استارتاپهای اپلیکیشن اندروید در Perfetto. روی برش مرتبط کلیک کنید و برای انتخاب برش، کلید m را فشار دهید. براکتها در اطراف برش ظاهر میشوند و مدت زمان صرف شده را نشان میدهند. مدت زمان نیز در برگه انتخاب فعلی نشان داده شده است.
با کلیک روی آیکون سنجاق، ردیف «راهاندازی برنامههای اندروید» را سنجاق کنید. این آیکون با نگه داشتن اشارهگر روی ردیف قابل مشاهده است.
به ردیفی که برنامه مورد نظر در آن قرار دارد بروید و روی اولین سلول کلیک کنید تا ردیف باز شود.
با فشار دادن w ، روی نخ اصلی، معمولاً در بالا، زوم کنید (برای کوچکنمایی، به ترتیب s، a، d را فشار دهید، به چپ و به راست حرکت کنید).

شکل ۳. برش متریک مشتقشده از استارتاپهای برنامه اندروید در کنار نخ اصلی برنامه. برش معیارهای مشتقشده، مشاهدهی دقیق آنچه در راهاندازی برنامه گنجانده شده است را آسانتر میکند، بنابراین میتوانید با جزئیات بیشتری به اشکالزدایی ادامه دهید.
هنگام تجزیه و تحلیل یک برنامه Jetpack Compose، میتوانید از ردیابی Composition برای مشاهده جزئیات دقیق در مورد عملکرد رابط کاربری خود استفاده کنید. به بخشهای ردیابی در thread اصلی که با Choreographer#doFrame شروع میشوند، توجه ویژهای داشته باشید. به دنبال برشهایی مانند Compose:recompose ، Compose:layout و Compose:draw . این برشها به شما نشان میدهند که برنامه شما چقدر زمان صرف ترکیب، اندازهگیری و قرار دادن و ترسیم اجزای خاص میکند.
از معیارها برای بررسی و بهبود استارتاپها استفاده کنید
برای تشخیص صحیح عملکرد زمان شروع، میتوانید معیارهایی را که نشان میدهند برنامه شما چقدر طول میکشد تا شروع به کار کند، پیگیری کنید. اندروید ابزارهای مختلفی را برای نشان دادن مشکل برنامه شما ارائه میدهد و به شما در تشخیص آن کمک میکند. Android Vitals میتواند به شما هشدار دهد که مشکلی در حال رخ دادن است و ابزارهای تشخیصی میتوانند به شما در تشخیص مشکل کمک کنند.
مزایای استفاده از معیارهای سنجش استارتاپ
اندروید از معیارهای زمان نمایش اولیه (TTID) و زمان نمایش کامل (TTFD) برای بهینهسازی راهاندازی سرد و گرم برنامه استفاده میکند. Android Runtime (ART) از دادههای این معیارها برای پیشکامپایل کارآمد کد جهت بهینهسازی راهاندازیهای آینده استفاده میکند.
راهاندازی سریعتر منجر به تعامل پایدارتر کاربر با برنامه شما میشود که موارد خروج زودهنگام، راهاندازی مجدد برنامه یا رفتن به برنامهای دیگر را کاهش میدهد.
نکات مهم اندروید
موارد حیاتی اندروید میتوانند با هشدار دادن به شما در کنسول Play در صورت طولانی شدن زمان راهاندازی برنامه، به بهبود عملکرد برنامه شما کمک کنند.
Android Vitals زمانهای راهاندازی زیر را برای برنامه شما بیش از حد در نظر میگیرد:
- روشن شدن سرد ۵ ثانیه یا بیشتر طول میکشد.
- روشن شدن گرم ۲ ثانیه یا بیشتر طول میکشد.
- روشن شدن سریع ۱.۵ ثانیه یا بیشتر طول میکشد.
Android Vitals از معیار زمان نمایش اولیه (TTID) استفاده میکند. برای اطلاعات بیشتر در مورد نحوه جمعآوری دادههای Android Vitals توسط Google Play، به مستندات Play Console مراجعه کنید.
زمان نمایش اولیه
زمان نمایش اولیه (TTID) مدت زمانی است که طول میکشد تا اولین فریم از رابط کاربری برنامه نمایش داده شود. این معیار، مدت زمانی را که طول میکشد تا یک برنامه اولین فریم خود را تولید کند، اندازهگیری میکند، از جمله مقداردهی اولیه فرآیند در طول شروع سرد، ایجاد فعالیت در طول شروع سرد یا گرم، و نمایش اولین فریم. پایین نگه داشتن TTID برنامه شما با اجازه دادن به کاربران برای مشاهده راهاندازی سریع برنامه، به بهبود تجربه کاربری کمک میکند. TTID به طور خودکار برای هر برنامه توسط چارچوب اندروید گزارش میشود. هنگام بهینهسازی برای شروع برنامه، توصیه میکنیم reportFullyDrawn برای دریافت اطلاعات تا TTFD پیادهسازی کنید.
TTID به عنوان یک مقدار زمانی اندازهگیری میشود که نشان دهنده کل زمان سپری شده است که شامل توالی رویدادهای زیر است:
- راهاندازی فرآیند.
- مقداردهی اولیه اشیاء.
- ایجاد و مقداردهی اولیه فعالیت میزبان.
- مقداردهی اولیه رابط کاربری.
- نقاشی کشیدن در برنامه برای اولین بار.
بازیابی TTID
برای یافتن TTID، در ابزار خط فرمان Logcat به دنبال یک خط خروجی حاوی مقداری به نام Displayed بگردید. این مقدار TTID است و شبیه به مثال زیر است که در آن TTID برابر با 3s534ms است:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
برای یافتن TTID در اندروید استودیو، فیلترها را در نمای Logcat خود از منوی کشویی فیلتر غیرفعال کنید و سپس زمان Displayed را همانطور که در شکل ۴ نشان داده شده است، پیدا کنید. غیرفعال کردن فیلترها ضروری است زیرا سرور سیستم، نه خود برنامه، این گزارش را ارائه میدهد.

Displayed در Logcat. معیار Displayed در خروجی Logcat لزوماً مدت زمان لازم برای بارگذاری و نمایش همه منابع را نشان نمیدهد. این معیار، منابعی را که در ترکیب اولیه به آنها اشاره نشده است (مانند دادهها یا تصاویر بارگذاری شده به صورت ناهمگام) یا منابعی را که برنامه به عنوان بخشی از مقداردهی اولیه شیء ایجاد میکند، حذف میکند. این معیار این منابع را حذف میکند زیرا بارگذاری آنها یک فرآیند درونخطی است و نمایش اولیه برنامه را مسدود نمیکند. برای اطلاعات بیشتر در مورد منابع، به بخش منابع در ترکیب مراجعه کنید.
گاهی اوقات خط Displayed در خروجی Logcat شامل یک فیلد اضافی برای کل زمان است، مانند مثال زیر:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
در این حالت، اندازهگیری زمان اولیه فقط برای فعالیتی است که برای اولین بار ترسیم میشود، که معمولاً فعالیت میزبان است. اندازهگیری زمان total از شروع فرآیند برنامه شروع میشود و میتواند شامل فعالیت دیگری باشد که ابتدا شروع شده است اما چیزی را روی صفحه نمایش نمیدهد. اندازهگیری زمان total فقط زمانی نشان داده میشود که بین زمانهای شروع یک فعالیت واحد و کل زمانهای راهاندازی تفاوت وجود داشته باشد.
ما استفاده از Logcat را در اندروید استودیو توصیه میکنیم، اما اگر از اندروید استودیو استفاده نمیکنید، میتوانید با اجرای برنامه خود با دستور adb shell activity manager ، TTID را نیز اندازهگیری کنید. در اینجا مثالی آورده شده است:
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 برنامه شما با فراهم کردن امکان تعامل سریع کاربران با برنامه شما، به بهبود تجربه کاربری کمک میکند.
اگرچه سیستم میتواند TTID را هنگامی که پنجره میزبان فریم اولیه خود را رندر میکند، تعیین کند، اما نمیتواند به طور خودکار TTFD را تعیین کند. از آنجا که برنامهها اغلب محتوای اصلی خود را به صورت ناهمزمان بارگذاری میکنند، سیستم نمیداند چه زمانی برنامه واقعاً برای کاربر کاملاً قابل استفاده است. برای تعیین TTFD، برنامه باید وقتی به حالت کاملاً ترسیم شده میرسد، به سیستم سیگنال دهد.
بازیابی TTFD
برای یافتن TTFD، با فراخوانی متد reportFullyDrawn از ComponentActivity ، وضعیت رسم کامل را اعلام کنید. متد reportFullyDrawn گزارش میدهد که برنامه چه زمانی به طور کامل رسم شده و در حالت قابل استفاده قرار دارد. TTFD زمان سپری شده از زمانی است که سیستم، intent اجرای برنامه را دریافت میکند تا زمانی که reportFullyDrawn فراخوانی میشود. اگر reportFullyDrawn فراخوانی نکنید، هیچ مقداری از TTFD گزارش نمیشود.
برای اندازهگیری TTFD، پس از اینکه رابط کاربری و تمام دادهها را بهطور کامل ترسیم کردید، تابع reportFullyDrawn را فراخوانی کنید. قبل از اینکه پنجره اولین فعالیت ابتدا ترسیم و مطابق اندازهگیری سیستم نمایش داده شود، تابع reportFullyDrawn فراخوانی نکنید، زیرا در این صورت سیستم زمان اندازهگیری شده توسط سیستم را گزارش میدهد. به عبارت دیگر، اگر قبل از اینکه سیستم TTID را تشخیص دهد، تابع reportFullyDrawn را فراخوانی کنید، سیستم هم TTID و هم TTFD را به یک مقدار گزارش میکند و این مقدار، مقدار TTID است.
وقتی از reportFullyDrawn استفاده میکنید، Logcat خروجی مانند مثال زیر را نمایش میدهد که در آن TTFD برابر با ۱s54ms است:
system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
خروجی Logcat گاهی اوقات شامل total زمان است، همانطور که در بخش «زمان تا نمایش اولیه» بحث شده است.
اگر زمان نمایش شما کندتر از آن چیزی است که میخواهید، میتوانید سعی کنید گلوگاههای فرآیند راهاندازی را شناسایی کنید.
شما میتوانید از reportFullyDrawn برای اعلام وضعیت ترسیمشدهی کامل در موارد اساسی که از دستیابی به وضعیت ترسیمشدهی کامل آگاه هستید، استفاده کنید. با این حال، در مواردی که نخهای پسزمینه باید قبل از دستیابی به وضعیت ترسیمشدهی کامل، کار پسزمینه را انجام دهند، برای اندازهگیری دقیقتر TTFD باید reportFullyDrawn به تأخیر بیندازید. برای یادگیری نحوهی به تأخیر انداختن reportFullyDrawn ، به بخش زیر مراجعه کنید.
بهبود دقت زمانبندی راهاندازی
اگر برنامه شما بارگذاری تنبل (lazy loading) را انجام میدهد و نمایش اولیه شامل تمام منابع نمیشود، مانند زمانی که برنامه شما تصاویر را از شبکه دریافت میکند، ممکن است بخواهید فراخوانی تابع reportFullyDrawn را تا زمانی که برنامه شما قابل استفاده شود، به تعویق بیندازید تا بتوانید جمعیت لیست را به عنوان بخشی از زمانبندی معیار خود لحاظ کنید.
برای مثال، اگر رابط کاربری شامل یک لیست پویا، مانند LazyColumn یا LazyRow باشد، ممکن است توسط یک وظیفه پسزمینه که پس از اولین ترسیم لیست و بنابراین پس از علامتگذاری رابط کاربری به عنوان ترسیم کامل، تکمیل میشود، پر شود. در چنین مواردی، جمعیت لیست در معیارسنجی لحاظ نمیشود.
برای گنجاندن جمعیت لیست به عنوان بخشی از زمانبندی معیار خود، با استفاده از fullyDrawnReporter ، FullyDrawnReporter دریافت کنید و یک گزارشگر به آن در کد برنامه خود اضافه کنید. گزارشگر را پس از اتمام پر کردن لیست توسط وظیفه پسزمینه، رها کنید.
FullyDrawnReporter تا زمانی که همه گزارشگرهای اضافه شده آزاد نشوند، متد reportFullyDrawn فراخوانی نمیکند. با اضافه کردن یک گزارشگر اما عدم انتشار آن تا زمان تکمیل فرآیند پسزمینه، مطمئن میشوید که دادههای زمانبندی راهاندازی شامل زمان جمعیت لیست است، بدون اینکه رفتار برنامه برای کاربر تغییر کند. reportFullyDrawn تا زمانی که همه وظایف، صرف نظر از ترتیب آنها، تکمیل نشده باشند، فراخوانی نمیشود.
اگر برنامه شما از Jetpack Compose استفاده میکند، میتوانید از APIهای زیر برای نشان دادن حالت کاملاً ترسیمشده استفاده کنید:
-
ReportDrawn: نشان میدهد که ترکیببندی شما بلافاصله برای تعامل آماده است. -
ReportDrawnWhen: یک گزاره مانندlist.count > 0میگیرد تا نشان دهد چه زمانی composable شما برای تعامل آماده است. -
ReportDrawnAfter: یک متد تعلیقی میگیرد که پس از تکمیل، نشان میدهد که composable شما برای تعامل آماده است.
مثال زیر نشان میدهد که چگونه میتوانید چندین وظیفه پسزمینه را همزمان اجرا کنید، و هر کدام گزارشگر خود را ثبت کنند:
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 {
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
}
}
}
}
شناسایی گلوگاهها
برای یافتن گلوگاهها، میتوانید از Android Studio CPU Profiler استفاده کنید. برای اطلاعات بیشتر، به «بازرسی فعالیت CPU با CPU Profiler» مراجعه کنید.
همچنین میتوانید از طریق ردیابی درونخطی (inline tracing) در داخل متدهای onCreate برنامهها و فعالیتهای خود، بینشی نسبت به گلوگاههای احتمالی به دست آورید. برای کسب اطلاعات در مورد ردیابی درونخطی، به مستندات توابع Trace و مرور کلی ردیابی سیستم مراجعه کنید.
حل مسائل رایج
این بخش به بررسی چندین مسئله میپردازد که اغلب بر عملکرد راهاندازی برنامه تأثیر میگذارند. این مسائل عمدتاً مربوط به مقداردهی اولیه اشیاء برنامه و فعالیت و همچنین بارگذاری صفحات هستند.
مقداردهی اولیه سنگین برنامه
وقتی کد شما شیء Application را override میکند و هنگام مقداردهی اولیه آن شیء، کارهای سنگین یا منطق پیچیدهای را اجرا میکند، عملکرد راهاندازی میتواند دچار مشکل شود. اگر زیرکلاسهای Application شما مقداردهیهای اولیهای را انجام دهند که هنوز نیازی به انجام آنها نیست، ممکن است برنامه شما در هنگام راهاندازی زمان زیادی را هدر دهد.
برخی از مقداردهیهای اولیه ممکن است کاملاً غیرضروری باشند، مانند زمان مقداردهی اولیه اطلاعات وضعیت برای فعالیت اصلی، زمانی که برنامه در واقع در پاسخ به یک intent راهاندازی میشود. با یک intent، برنامه فقط از زیرمجموعهای از دادههای وضعیت قبلاً مقداردهی شده استفاده میکند.
چالشهای دیگر در طول راهاندازی برنامه شامل رویدادهای جمعآوری زباله (garbage collection) است که تأثیرگذار یا متعدد هستند، یا I/O دیسک که همزمان با راهاندازی اتفاق میافتد، که فرآیند راهاندازی را بیشتر مسدود میکند. جمعآوری زباله به ویژه در زمان اجرای Dalvik مورد توجه است؛ زمان اجرای اندروید (ART) جمعآوری زباله را به طور همزمان انجام میدهد و تأثیر آن عملیات را به حداقل میرساند.
تشخیص مشکل
میتوانید از ردیابی متد یا ردیابی درونخطی برای تشخیص مشکل استفاده کنید.
ردیابی روش
اجرای CPU Profiler نشان میدهد که متد callApplicationOnCreate در نهایت متد com.example.customApplication.onCreate شما را فراخوانی میکند. اگر ابزار نشان دهد که اجرای این متدها مدت زمان زیادی طول میکشد، بیشتر بررسی کنید تا ببینید چه کاری در آنجا انجام میشود.
ردیابی درون خطی
از ردیابی درونخطی برای بررسی عوامل احتمالی، از جمله موارد زیر، استفاده کنید:
- تابع
onCreateاولیه برنامه شما. - هر شیء سینگلتون سراسری که برنامه شما مقداردهی اولیه میکند.
- هرگونه ورودی/خروجی دیسک، deserialization یا حلقههای تنگ که ممکن است در طول گلوگاه رخ دهد.
راه حل های مشکل
چه مشکل مربوط به مقداردهی اولیه غیرضروری باشد و چه مربوط به ورودی/خروجی دیسک، راه حل مقداردهی اولیه کند (lazy initialization) است. به عبارت دیگر، فقط اشیاء مورد نیاز فوری را مقداردهی اولیه کنید. به جای ایجاد اشیاء استاتیک سراسری، به الگوی singleton بروید که در آن برنامه فقط در اولین باری که به اشیاء نیاز دارد، آنها را مقداردهی اولیه میکند.
همچنین، استفاده از یک چارچوب تزریق وابستگی مانند Hilt را در نظر بگیرید که اشیاء و وابستگیها را هنگام تزریق برای اولین بار ایجاد میکند.
اگر برنامه شما از ارائه دهندگان محتوا برای مقداردهی اولیه اجزای برنامه در هنگام راهاندازی استفاده میکند، به جای آن از کتابخانه App Startup استفاده کنید.
مقداردهی اولیه فعالیت سنگین
ایجاد فعالیت اغلب مستلزم کار سربار زیادی است. اغلب، فرصتهایی برای بهینهسازی این کار برای دستیابی به بهبود عملکرد وجود دارد. چنین مسائل رایجی شامل موارد زیر است:
- مقداردهی اولیه یک رابط کاربری بزرگ یا پیچیده.
- مقداردهی اولیه سنگین در composableها.
- مسدود کردن ترسیم صفحه روی دیسک یا ورودی/خروجی شبکه.
- بارگذاری و رمزگشایی بیتمپها
- تبدیل اشیاء
VectorDrawableبه تصویر شطرنجی. - مقداردهی اولیه سایر زیرسیستمهای فعالیت میزبان برنامه.
تشخیص مشکل
در این مورد نیز، هم ردیابی متد و هم ردیابی درونخطی میتوانند مفید باشند.
ردیابی روش
هنگام استفاده از CPU Profiler، به سازندههای زیرکلاس Application و متدهای com.example.customApplication.onCreate برنامه خود توجه کنید.
اگر ابزار نشان دهد که اجرای این متدها مدت زیادی طول میکشد، بیشتر بررسی کنید تا ببینید چه کاری در آنجا انجام میشود.
ردیابی درون خطی
از ردیابی درونخطی برای بررسی عوامل احتمالی، از جمله موارد زیر، استفاده کنید:
- تابع
onCreateاولیه برنامه شما. - هر شیء سینگلتون سراسری که مقداردهی اولیه شود.
- هرگونه ورودی/خروجی دیسک، deserialization یا حلقههای تنگ که ممکن است در طول گلوگاه رخ دهد.
راه حل های مشکل
گلوگاههای بالقوه زیادی وجود دارد، اما دو مشکل رایج و راهحلهای آنها به شرح زیر است:
- هرچه سلسله مراتب رابط کاربری شما بزرگتر باشد، زمان بیشتری برای مقداردهی اولیه برنامه صرف میشود. هنگام رسیدگی به این مشکل، مراحل زیر را در نظر بگیرید:
- با کاهش کامپوننتهای اضافی یا تو در تو، سلسله مراتب رابط کاربری خود را مسطح کنید.
- از ترکیب و ترکیب مجدد غیرضروری در حین پرتاب خودداری کنید.
- ترکیب رابط کاربری غیر حیاتی را به تعویق بیندازید.
- قرار دادن تمام مقداردهی اولیه منابع در نخ اصلی میتواند باعث کندی راهاندازی نیز شود. میتوانید این مشکل را به صورت زیر حل کنید:
- تمام مقداردهی اولیه منابع را جابجا کنید تا برنامه بتواند آن را به صورت تنبل (lazy) روی یک نخ متفاوت انجام دهد.
- ابتدا رابط کاربری خود را با دادههای placeholder بارگذاری و نمایش دهید، و سپس بعداً ویژگیهای بصری وابسته به بیتمپها و سایر منابع را بهروزرسانی کنید.
برای اطلاعات بیشتر در مورد ترکیب مجدد، به Recomposition و Get recomposition counts مراجعه کنید.
صفحههای نمایش چلپ چلوپ سفارشی
اگر قبلاً از یکی از روشهای زیر برای پیادهسازی صفحه شروع سفارشی در اندروید ۱۱ (سطح API 30) یا قبل از آن استفاده کرده باشید، ممکن است در هنگام راهاندازی زمان اضافی اضافه شود:
- استفاده از ویژگی تم
windowDisablePreviewبرای خاموش کردن صفحه خالی اولیه که توسط سیستم در هنگام راهاندازی ترسیم میشود. - استفاده از یک
Activityاختصاصی.
با شروع اندروید ۱۲، مهاجرت به API SplashScreen الزامی است. این API زمان راهاندازی سریعتری را فراهم میکند و به شما امکان میدهد صفحه شروع خود را به روشهای زیر تنظیم کنید:
- برای تغییر ظاهر صفحه شروع، یک تم تنظیم کنید .
- مدت زمان نمایش صفحه شروع را با
windowSplashScreenAnimationDurationکنترل کنید. - انیمیشن صفحه شروع را سفارشی کنید و انیمیشن مربوط به حذف صفحه شروع را به زیبایی مدیریت کنید.
علاوه بر این، کتابخانه compat، رابط برنامهنویسی کاربردی SplashScreen را پشتیبانی میکند تا امکان سازگاری با نسخههای قبلی را فراهم کند و ظاهر و حس ثابتی برای نمایش صفحه شروع در تمام نسخههای اندروید ایجاد کند.
برای جزئیات بیشتر به راهنمای مهاجرت به صفحه Splash مراجعه کنید.
{% کلمه به کلمه %}برای شما توصیه میشود
- توجه: متن لینک زمانی نمایش داده میشود که جاوا اسکریپت غیرفعال باشد.
- رندرینگ آهسته
- ثبت معیارهای Macrobenchmark
- ایجاد پروفایلهای پایه{:#creating-profile-rules}