ANR (Application Not Responding) هو إشعار نظام Android يظهر عندما يتوقف التطبيق عن الاستجابة لإدخال المستخدم لأكثر من 5 ثوانٍ. وفقًا لـ Android Developers، السبب الرئيسي هو العمليات الطويلة على الخيط الرئيسي التي تمنع معالجة اللمس وعرض الواجهة. فهم آليات ANR ضروري لكل مطور Android لإنشاء تطبيقات سريعة الاستجابة.
الخلاصة
ANR (Application Not Responding) هو مربع حوار لنظام التشغيل Android يظهر عندما يتوقف التطبيق عن الاستجابة لإدخال المستخدم. يتتبع النظام وقت معالجة الأحداث من خلال InputDispatcher: إذا لم تتم معالجة لمسة أو ضغطة زر خلال 5 ثوانٍ، يعرض Android حوارًا يطلب إغلاق التطبيق أو الانتظار.
آلية ANR تحمي تجربة المستخدم من التطبيقات المجمدة. لا يسمح Android لتطبيق واحد بحظر النظام بأكمله — على عكس أنظمة سطح المكتب، تحد المنصة المحمولة إجباريًا وقت معالجة الأحداث. BroadcastReceiver لديه حد 10 ثوانٍ، والخدمة الأمامية لديها 20 ثانية.
ANR ليس استثناءً في الكود — إنها آلية نظام على مستوى عمليات Linux. يرسل Android إشارة SIGQUIT إلى العملية، وبعدها يحفظ النظام مكدس استدعاءات جميع الخيوط في ملف traces.txt. لا يتلقى المطور ANR كاستثناء catch، بل كتقرير بعد إعادة تشغيل التطبيق. على Android 11+، تسمح واجهة برمجة التطبيقات ApplicationExitInfo بالحصول برمجيًا على سبب إنهاء العملية، بما في ذلك ANR — مما يبسط جمع الإحصائيات دون الحاجة إلى تحليل traces.txt يدويًا.
خمس فئات من العمليات تؤدي باستمرار إلى ANR في تطبيقات Android. كل منها يحظر الخيط الرئيسي، مما يمنع النظام من معالجة أحداث الإدخال وإعادة رسم الشاشة.
طلبات HTTP المتزامنة المنفذة على خيط UI هي السبب الأكثر شيوعًا لـ ANR بين المطورين المبتدئين. حتى الطلب السريع للخادم يمكن أن يستغرق 1–3 ثوانٍ، ومع اتصال ضعيف — 30 ثانية أو أكثر. يمنع Android صراحة عمليات الشبكة على الخيط الرئيسي بدءًا من API 11، مما يطرح NetworkOnMainThreadException.
استخدم Coroutines أو RxJava للاستدعاءات غير المتزامنة. تنفذ coroutines مع dispatcher Dispatchers.IO الطلب في خلفية وتنقل النتيجة إلى الخيط الرئيسي عبر Dispatchers.Main. هذا يلغي تمامًا حظر خيط UI بواسطة عمليات الشبكة.
fun fetchUserData() {
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.IO) {
api.getUserData() // عملية في الخلفية
}
updateUI(result) // النتيجة على الخيط الرئيسي
}
}
معالجة مصفوفات البيانات الكبيرة، تحليل JSON أو XML، العمل مع الصور النقطية مباشرة على الخيط الرئيسي — ثاني أكثر أسباب ANR شيوعًا. حتى 300 مللي ثانية من العمل المستمر لخيط UI دون العودة إلى حلقة الأحداث تسبب تأخيرًا ملحوظًا في العرض، وحد الـ 5 ثوانٍ يُسجل كـ ANR.
WorkManager والخدمات الخلفية مصممة لنقل الحسابات الثقيلة خارج الخيط الرئيسي. استخدم AsyncTask (قديم)، ListenableFuture أو Kotlin Flow لنقل البيانات على دفعات دون حظر واجهة المستخدم.
يحدث Deadlock عندما يحمل خيطان أقفالًا وينتظر كل منهما الآخر. إذا كان أحد الخيوط هو الخيط الرئيسي، يسجل النظام ANR بعد 5 ثوانٍ بالضبط. Thread.join() و CountDownLatch.await() وكتل synchronized المستدعاة من خيط UI تحمل خطر الحظر.
تجنب أي عمليات حظر على الخيط الرئيسي. بدلاً من synchronized، استخدم ConcurrentHashMap؛ بدلاً من Thread.join() — coroutines مع async/await. تنطبق هذه القاعدة على أي لغة في Android: Java أو Kotlin أو C++ عبر JNI.
يتم تنفيذ BroadcastReceiver على الخيط الرئيسي افتراضيًا. إذا كان onReceive() مشغولاً لأكثر من 10 ثوانٍ، يعرض Android ANR. تحميل البيانات من قاعدة البيانات أو الشبكة داخل onReceive هو طريق مضمون للتجميد.
استخدم goAsync() داخل BroadcastReceiver للتبديل إلى خيط خلفية، أو registerReceiver مع getBackgroundBroadcastReceiver(). هذا يسمح بمعالجة الأحداث دون حظر واجهة المستخدم.
استعلامات ثقيلة لـ ContentProvider أو العمل المباشر مع SQLite على خيط UI — سبب أقل وضوحًا ولكنه شائع لـ ANR. أثناء ترحيل قاعدة البيانات أو الإدراج الجماعي لآلاف السجلات، قد يتجاوز وقت التنفيذ حد الـ 5 ثوانٍ.
انقل جميع عمليات قاعدة البيانات إلى خيوط خلفية باستخدام Room مع دوال suspend. يتحقق Room تلقائيًا من أن الاستعلام لا يتم تنفيذه على الخيط الرئيسي ويطرح استثناءً في حالة المخالفة.
تشخيص ANR يختلف عن تصحيح الاستثناءات العادية — لا يمكنك التقاط ANR في كتلة try-catch. مصدر المعلومات الرئيسي هو ملف traces.txt، الذي ينشئه Android في لحظة التجميد.
traces.txt يحتوي على مكدس استدعاءات جميع خيوط التطبيق في وقت ANR. لقراءة الملف من جهاز حقيقي، نفذ الأمر adb bugreport، الذي يجمع تقريرًا كاملاً للنظام بما في ذلك جميع ANRs الأخيرة. للمحاكي، الملف متاح في /data/anr/traces.txt. يظهر مكدس الاستدعاءات أي طريقة كانت تُنفذ على الخيط الرئيسي في لحظة الحظر.
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt
Google Play Console توفر قسم ANR & Crash مع تقارير مجمعة وتكرارات الأخطاء. لكل ANR، يُظهر مكدس الاستدعاءات وإحصائيات الجهاز: الطراز، إصدار Android، المنطقة. هذا يسمح بتحديد ANRs التي تعتمد على أجهزة أو إصدارات نظام محددة.
Android Studio منذ 2021 يحتوي على ANR Watchdog في الموصف. يسجل تلقائيًا تفريغات الخيوط إذا لم يستجب الخيط الرئيسي لأكثر من وقت حدي. تظهر الأداة خطًا زمنيًا للأحداث: أي العمليات بدأت، وأي الطرق نُفذت، وفي أي مرحلة حدث الحظر.
تستند الوقاية من ANR إلى قاعدة أساسية واحدة: يجب أن يعالج الخيط الرئيسي أحداث UI فقط. أي عملية أطول من 16 مللي ثانية (وقت إطار واحد) يجب أن تُنفذ في خيط خلفية.
StrictMode أداة Android مدمجة لاكتشاف ANRs المحتملة أثناء التطوير. فعّله في Application.onCreate() مع علامات لعمليات القرص والشبكة. عند المخالفة، يطرح StrictMode استثناءً أو يكتب في logcat.
if (BuildConfig.DEBUG) {
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
.let { StrictMode.setThreadPolicy(it) }
}
Kotlin Coroutines — الطريقة القياسية للعمل غير المتزامن في تطبيقات Android الحديثة. النهج الأساسي: عمليات الإدخال/الإخراج تُنفذ على Dispatchers.IO، النتيجة تُنقل إلى Dispatchers.Main لتحديثات UI. لسيناريوهات Flow، استخدم Dispatchers.Default للمهام كثيفة المعالجة.
RxJava يبقى شائعًا في المشاريع القديمة. subscribeOn(Schedulers.io()) و observeOn(AndroidSchedulers.mainThread()) — الحد الأدنى لمنع ANR. القاعدة الرئيسية نفسها: لا يجب أن يصدر أي Observable أو Flowable بيانات من الخيط الرئيسي.
Firebase Crashlytics منذ إصدار SDK 18.4.0 يدعم مراقبة ANR مباشرة. لنظام Android 11+، يستخدم Crashlytics واجهة برمجة التطبيقات النظامية ApplicationExitInfo التي توفر سبب الإنهاء الدقيق: ANR، Crash، أو قتل النظام. فعّل مفاتيح مخصصة مع معلمات الشاشة والحالة للتحليل السياقي.
خمس أدوات تغطي جميع مراحل العمل مع ANR: من التصحيح على محطة العمل إلى المراقبة في الإنتاج. كل أداة تحل مهمتها الخاصة وتوفر بيانات لسيناريوهات مختلفة.
| الأداة | الغرض | تنسيق البيانات |
|---|---|---|
| StrictMode | الاكتشاف أثناء التطوير | Logcat / Exception |
| ANR Watchdog (Android Studio) | التتبع في الوقت الفعلي | Thread dump + timeline |
| Google Play Console | إحصائيات مجمعة | ANR rate + stack traces |
| Firebase Crashlytics | مراقبة الإنتاج | ApplicationExitInfo |
| adb bugreport | تقرير نظام كامل | traces.txt + logcat + dmesg |
كل أداة لها مجالها الخاص: StrictMode يلتقط المخالفات الواضحة في المراحل المبكرة، Crashlytics يظهر التكرار الحقيقي لـ ANR بين المستخدمين، و adb bugreport يوفر الصورة الأكثر اكتمالاً للحالات المعقدة. ادمجها للتغطية الكاملة.
Firebase Performance يتتبع وقت استجابة خيط UI وينشئ تلقائيًا تتبعات للعمليات الطويلة بشكل مريب. إذا حظر الخيط الرئيسي لأكثر من 500 مللي ثانية، يسجل Performance تتبعًا مخصصًا باسم الطريقة المسببة. هذا يسمح باكتشاف سيناريوهات ANR دون تدخل المستخدم وقبل أن تصبح حرجة.
التكامل مع Firebase Crashlytics يعطي صورة كاملة: Performance يظهر التباطؤ قبل ANR، و Crashlytics يظهر التجميد نفسه. قم بإعداد تنبيهات في Firebase Console لمعدل ANR أعلى من 0.1%، وستتلقى إشعارات حول المشكلات الجديدة قبل شكاوى المستخدمين الجماعية.
الأسئلة الشائعة
ANR هو تجميد حيث لا يستجيب التطبيق ولكنه يبقى في الذاكرة. Crash هو إنهاء غير طبيعي كامل مع خروج من العملية. ANR يمكن «النجاة منه» إذا انتظر النظام أو المستخدم استجابة، بينما Crash دائمًا ينهي التطبيق.
لا. ANR ليس استثناء Java/Kotlin، بل إشارة نظام على مستوى العمليات (SIGQUIT). لا يمكن للمطور معالجته في كود التطبيق. الطريقة الوحيدة للاستجابة لـ ANR هي تحليل التقارير بعد إعادة التشغيل.
أداء الجهاز، إصدار Android، تحميل CPU وعدد العمليات الخلفية تؤثر على احتمالية ANR. على الأجهزة الضعيفة، نفس العملية قد تستغرق 2–3 مرات أطول، متجاوزة حد 5 ثوانٍ.
10 ثوانٍ لـ BroadcastReceiver عادي في onReceive(). للخدمات الأمامية، الحد هو 20 ثانية، ولـ ContentProvider — لا يوجد حد صريح، لكن حظر الخيط الرئيسي لأكثر من 5 ثوانٍ لا يزال يسبب ANR.
فعّل StrictMode في جميع إصدارات التصحيح، أضف مراقبة عبر Firebase Crashlytics، واستخدم adb bugreport عندما يحدث ANR. ANRs غير المنتظمة غالبًا ما ترتبط بظروف تسابق أو حالات شبكة محددة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا