این سند توضیح میدهد که چگونه سیستم Android تشخیص میدهد که آیا یک برنامه پاسخ نمیدهد یا خیر و نشان میدهد که چگونه برنامه خود را پاسخگو نگه دارید.
مهم نیست که کد شما چقدر خوب نوشته شده باشد، ممکن است برنامه شما همچنان کند باشد، هنگ کند، برای دوره های قابل توجهی ثابت بماند یا پردازش ورودی بیش از حد طول بکشد. اگر برنامه شما در پیش زمینه باشد و پاسخگو نباشد، کاربر یک گفتگوی Application Not Responding (ANR) دریافت می کند، همانطور که در شکل 1 نشان داده شده است. گفتگوی ANR به کاربر اجازه می دهد تا به اجبار از برنامه خارج شود. اگر برنامه در پیش زمینه نباشد، بی سر و صدا متوقف می شود. برای به حداقل رساندن دیالوگ های ANR، طراحی پاسخگویی در برنامه شما بسیار مهم است.
ANR باعث می شود
به طور کلی، اگر برنامهای نتواند به ورودی کاربر در رشته اصلی (که به عنوان رشته رابط کاربری نیز شناخته میشود) پاسخ دهد، سیستم یک ANR نشان میدهد و از پردازش رویدادهای ورودی کاربر توسط سیستم جلوگیری میکند.
به عنوان مثال، اگر یک برنامه یک عملیات مسدودکننده ورودی/خروجی، مانند دسترسی به شبکه، را در رشته رابط کاربری انجام دهد، ANR ممکن است رخ دهد. مثال دیگر زمانی است که یک برنامه زمان زیادی را صرف ساختن یک ساختار پیچیده در حافظه یا محاسبه حرکت بعدی در یک بازی در رشته UI می کند.
در اندروید، پاسخگویی برنامه توسط خدمات سیستم ActivityManager
و WindowManager
نظارت می شود. Android زمانی که برنامه یکی از شرایط زیر را تشخیص دهد، گفتگوی ANR را برای یک برنامه نمایش می دهد:
- بدون پاسخ به یک رویداد ورودی - مانند فشار دادن کلید یا رویدادهای ضربه زدن روی صفحه - در عرض 5 ثانیه.
- یک
BroadcastReceiver
برای اهداف پیشزمینه، در عرض 10 تا 20 ثانیه به پایان نمیرسد. برای اطلاعات بیشتر، مهلت زمانی گیرنده پخش را ببینید.
از ANR اجتناب کنید
در زیر نکات کلی برای جلوگیری از ANR آمده است. برای جزئیات بیشتر در مورد تشخیص و اشکال زدایی انواع مختلف ANR، به صفحات دیگر در این بخش مراجعه کنید.
تاپیک اصلی را همیشه بدون انسداد نگه دارید و از موضوعات استراتژیک استفاده کنید.
از انجام عملیات مسدود کردن یا طولانی مدت در رشته اصلی برنامه خودداری کنید. در عوض، یک تاپیک کارگر ایجاد کنید و بیشتر کار را در آنجا انجام دهید.
سعی کنید هر گونه اختلاف قفل بین نخ اصلی و سایر رشته ها را به حداقل برسانید.
کارهای غیرمرتبط با رابط کاربری را در رشته اصلی به حداقل برسانید، مانند هنگام مدیریت پخش یا اجرای خدمات. هر روشی که در رشته UI اجرا می شود باید تا حد امکان کمتر روی آن رشته کار کند. به طور خاص، فعالیتها باید تا حد امکان کمتر برای راهاندازی روشهای چرخه حیات کلیدی، مانند
onCreate()
وonResume()
انجام دهند. برای اطلاعات بیشتر در مورد راه حل های موجود برای زمان بندی کار در یک رشته پس زمینه و برقراری ارتباط مجدد با رابط کاربری، به نمای کلی کار پس زمینه مراجعه کنید.هنگام به اشتراک گذاشتن thread pools بین اجزا مراقب باشید. از رشتههای مشابه برای عملیات مسدود کردن طولانی مدت و کارهای حساس به زمان مانند دریافت پخش استفاده نکنید.
راه اندازی برنامه را سریع نگه دارید. عملیات آهسته یا مسدود کردن را در کد راهاندازی برنامه، مانند روشهایی که در حین اولیهسازی خنجر اجرا میشوند، به حداقل برسانید.
اگر از
BroadcastReceiver
استفاده می کنید، گیرنده های پخش را در یک رشته غیر اصلی با استفاده ازContext.registerReceiver
اجرا کنید. برای اطلاعات بیشتر، ANR ها را در BroadcastReceiver ببینید.- اگر از
goAsync()
استفاده میکنید، مطمئن شوید کهPendingResult.finish
قبل از وقفه ANR به سرعت فراخوانی شده است.
- اگر از
ANR در BroadcastReceiver
زمان اجرای BroadcastReceiver
محدود است زیرا گیرندههای پخش برای انجام کارهای کوچک و مجزا در پسزمینه، مانند ذخیره یک تنظیم یا ثبت Notification
، قرار دارند. بنابراین، مانند سایر روشهایی که در رشته رابط کاربری نامیده میشوند، برنامهها باید از عملیات یا محاسبات طولانیمدت در گیرنده پخش اجتناب کنند. به جای انجام کارهای طولانی مدت از طریق رشته UI، آنها را در پس زمینه انجام دهید تا بعداً اجرا شوند. برای اطلاعات بیشتر در مورد راه حل های ممکن ، نمای کلی کار پس زمینه را ببینید.
یکی دیگر از مشکلات رایج در مورد اشیاء BroadcastReceiver
زمانی رخ می دهد که آنها به طور مکرر اجرا شوند. اجرای مکرر پسزمینه میتواند میزان حافظه موجود برای سایر برنامهها را کاهش دهد. برای اطلاعات بیشتر در مورد نحوه فعال کردن و غیرفعال کردن کارآمد اشیاء BroadcastReceiver
، به نمای کلی Broadcasts مراجعه کنید.
تقویت پاسخگویی
به طور کلی، 100 تا 200 میلیثانیه آستانهای است که کاربران پس از آن، کندی برنامه را درک میکنند. در اینجا نکات دیگری برای پاسخگو نشان دادن برنامه شما به کاربران وجود دارد:
اگر برنامه شما در پسزمینه در پاسخ به ورودی کاربر کار میکند، نشان دهید که پیشرفت در حال انجام است، مانند نوار
ProgressBar
در رابط کاربری شما.مخصوصاً برای بازی ها، محاسباتی را برای حرکات در یک نخ کارگر انجام دهید.
اگر برنامه شما مرحله راهاندازی اولیه زمانبر دارد، در نظر بگیرید که یک صفحه نمایش اسپلش نشان داده یا نمای اصلی را در سریعترین زمان ممکن نمایش دهید. نشان دهید که بارگیری در حال انجام است و اطلاعات را به صورت ناهمزمان پر کنید. در هر صورت، توصیه می کنیم به نحوی نشان دهید که پیشرفت در حال انجام است، به طوری که کاربر متوجه مسدود شدن برنامه نشود.
از ابزارهای عملکردی مانند Perfetto و CPU Profiler برای تعیین تنگناها در پاسخگویی برنامه خود استفاده کنید.
این سند توضیح میدهد که چگونه سیستم Android تشخیص میدهد که آیا یک برنامه پاسخ نمیدهد یا خیر و نشان میدهد که چگونه برنامه خود را پاسخگو نگه دارید.
مهم نیست که کد شما چقدر خوب نوشته شده باشد، ممکن است برنامه شما همچنان کند باشد، هنگ کند، برای دوره های قابل توجهی ثابت بماند یا پردازش ورودی بیش از حد طول بکشد. اگر برنامه شما در پیش زمینه باشد و پاسخگو نباشد، کاربر یک گفتگوی Application Not Responding (ANR) دریافت می کند، همانطور که در شکل 1 نشان داده شده است. گفتگوی ANR به کاربر اجازه می دهد تا به اجبار از برنامه خارج شود. اگر برنامه در پیش زمینه نباشد، بی سر و صدا متوقف می شود. برای به حداقل رساندن دیالوگ های ANR، طراحی پاسخگویی در برنامه شما بسیار مهم است.
ANR باعث می شود
به طور کلی، اگر برنامهای نتواند به ورودی کاربر در رشته اصلی (که به عنوان رشته رابط کاربری نیز شناخته میشود) پاسخ دهد، سیستم یک ANR نشان میدهد و از پردازش رویدادهای ورودی کاربر توسط سیستم جلوگیری میکند.
به عنوان مثال، اگر یک برنامه یک عملیات مسدودکننده ورودی/خروجی، مانند دسترسی به شبکه، را در رشته رابط کاربری انجام دهد، ANR ممکن است رخ دهد. مثال دیگر زمانی است که یک برنامه زمان زیادی را صرف ساختن یک ساختار پیچیده در حافظه یا محاسبه حرکت بعدی در یک بازی در رشته UI می کند.
در اندروید، پاسخگویی برنامه توسط خدمات سیستم ActivityManager
و WindowManager
نظارت می شود. Android زمانی که برنامه یکی از شرایط زیر را تشخیص دهد، گفتگوی ANR را برای یک برنامه نمایش می دهد:
- بدون پاسخ به یک رویداد ورودی - مانند فشار دادن کلید یا رویدادهای ضربه زدن روی صفحه - در عرض 5 ثانیه.
- یک
BroadcastReceiver
برای اهداف پیشزمینه، در عرض 10 تا 20 ثانیه به پایان نمیرسد. برای اطلاعات بیشتر، مهلت زمانی گیرنده پخش را ببینید.
از ANR اجتناب کنید
در زیر نکات کلی برای جلوگیری از ANR آمده است. برای جزئیات بیشتر در مورد تشخیص و اشکال زدایی انواع مختلف ANR، به صفحات دیگر در این بخش مراجعه کنید.
تاپیک اصلی را همیشه بدون انسداد نگه دارید و از موضوعات استراتژیک استفاده کنید.
از انجام عملیات مسدود کردن یا طولانی مدت در رشته اصلی برنامه خودداری کنید. در عوض، یک تاپیک کارگر ایجاد کنید و بیشتر کار را در آنجا انجام دهید.
سعی کنید هر گونه اختلاف قفل بین نخ اصلی و سایر رشته ها را به حداقل برسانید.
کارهای غیرمرتبط با رابط کاربری را در رشته اصلی به حداقل برسانید، مانند هنگام مدیریت پخش یا اجرای خدمات. هر روشی که در رشته UI اجرا می شود باید تا حد امکان کمتر روی آن رشته کار کند. به طور خاص، فعالیتها باید تا حد امکان کمتر برای راهاندازی روشهای چرخه حیات کلیدی، مانند
onCreate()
وonResume()
انجام دهند. برای اطلاعات بیشتر در مورد راه حل های موجود برای زمان بندی کار در یک رشته پس زمینه و برقراری ارتباط مجدد با رابط کاربری، به نمای کلی کار پس زمینه مراجعه کنید.هنگام به اشتراک گذاشتن thread pools بین اجزا مراقب باشید. از رشتههای مشابه برای عملیات مسدود کردن طولانی مدت و کارهای حساس به زمان مانند دریافت پخش استفاده نکنید.
راه اندازی برنامه را سریع نگه دارید. عملیات آهسته یا مسدود کردن را در کد راهاندازی برنامه، مانند روشهایی که در حین اولیهسازی خنجر اجرا میشوند، به حداقل برسانید.
اگر از
BroadcastReceiver
استفاده می کنید، گیرنده های پخش را در یک رشته غیر اصلی با استفاده ازContext.registerReceiver
اجرا کنید. برای اطلاعات بیشتر، ANR ها را در BroadcastReceiver ببینید.- اگر از
goAsync()
استفاده میکنید، مطمئن شوید کهPendingResult.finish
قبل از وقفه ANR به سرعت فراخوانی شده است.
- اگر از
ANR در BroadcastReceiver
زمان اجرای BroadcastReceiver
محدود است زیرا گیرندههای پخش برای انجام کارهای کوچک و مجزا در پسزمینه، مانند ذخیره یک تنظیم یا ثبت Notification
، قرار دارند. بنابراین، مانند سایر روشهایی که در رشته رابط کاربری نامیده میشوند، برنامهها باید از عملیات یا محاسبات طولانیمدت در گیرنده پخش اجتناب کنند. به جای انجام کارهای طولانی مدت از طریق رشته UI، آنها را در پس زمینه انجام دهید تا بعداً اجرا شوند. برای اطلاعات بیشتر در مورد راه حل های ممکن ، نمای کلی کار پس زمینه را ببینید.
یکی دیگر از مشکلات رایج در مورد اشیاء BroadcastReceiver
زمانی رخ می دهد که آنها به طور مکرر اجرا شوند. اجرای مکرر پسزمینه میتواند میزان حافظه موجود برای سایر برنامهها را کاهش دهد. برای اطلاعات بیشتر در مورد نحوه فعال کردن و غیرفعال کردن کارآمد اشیاء BroadcastReceiver
، به نمای کلی Broadcasts مراجعه کنید.
تقویت پاسخگویی
به طور کلی، 100 تا 200 میلیثانیه آستانهای است که کاربران پس از آن، کندی برنامه را درک میکنند. در اینجا نکات دیگری برای پاسخگو نشان دادن برنامه شما به کاربران وجود دارد:
اگر برنامه شما در پسزمینه در پاسخ به ورودی کاربر کار میکند، نشان دهید که پیشرفت در حال انجام است، مانند نوار
ProgressBar
در رابط کاربری شما.مخصوصاً برای بازی ها، محاسباتی را برای حرکات در یک نخ کارگر انجام دهید.
اگر برنامه شما مرحله راهاندازی اولیه زمانبر دارد، در نظر بگیرید که یک صفحه نمایش اسپلش نشان داده یا نمای اصلی را در سریعترین زمان ممکن نمایش دهید. نشان دهید که بارگیری در حال انجام است و اطلاعات را به صورت ناهمزمان پر کنید. در هر صورت، توصیه می کنیم به نحوی نشان دهید که پیشرفت در حال انجام است، به طوری که کاربر متوجه مسدود شدن برنامه نشود.
از ابزارهای عملکردی مانند Perfetto و CPU Profiler برای تعیین تنگناها در پاسخگویی برنامه خود استفاده کنید.