ANR (التطبيق لا يستجيب) - خطأ يحدث عندما لا يستجيب التطبيق. نتيجة لذلك ، يتم فتح مربع حوار يطالب المستخدم بالانتظار أو إغلاق التطبيق.

شروط ANR
- لا تتم معالجة أحداث الإدخال (الأزرار وأحداث اللمس) لمدة 5 ثوانٍ ؛
- لم تتم معالجة BroadcastReceiver (onRecieve ()) خلال الوقت المحدد (المقدمة - 10 ثانية ، الخلفية - 60 ثانية) ؛
- ContentProvider لم يكتمل خلال 10 ثوانٍ.
عادة ما يتم حظر الخيط الرئيسي.
إذا قرأت مقالاتي ، فربما تكون معتادًا على حقيقة أننا نقوم بالزحف إلى شفرة المصدر. لذلك دعونا نرى ما يشبه
ANR تحت غطاء محرك السيارة .
لا
تتعامل فئة
AppErrors مع ANR فحسب ، بل
تعالج أيضًا الأخطاء الأخرى التي قد تحدث في التطبيق ، بما في ذلك التعطل. يفتح الأسلوب handleShowAnrUi () هذه النافذة المخيفة للعديد من المطورين والمستخدمين الذين يعرضون ANR.
class AppErrors { ... void handleShowAnrUi(Message msg) { Dialog dialogToShow = null; synchronized (mService) { AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; final ProcessRecord proc = data.proc; if (proc == null) { Slog.e(TAG, "handleShowAnrUi: proc is null"); return; } if (proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.ALREADY_SHOWING); return; } Intent intent = new Intent("android.intent.action.ANR"); if (!mService.mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); } mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, 0 ); boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; if (mService.canShowErrorDialogs() || showBackground) { dialogToShow = new AppNotRespondingDialog(mService, mContext, data); proc.anrDialog = dialogToShow; } else { MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.CANT_SHOW);
ومع ذلك ، لا يبدأ ANR هنا. كما قلت أعلاه ، أحد الأسباب الأولى لهذا الخطأ هو تأخير حدث الإدخال ، وهو 5 ثوانٍ. من خلال البحث القصير يمكننا العثور على مكان تعيين هذه القيمة.
namespace android {
الآن يمكننا أن ننظر في رمز حيث يسمى الجزء الأصلي. يحدث هذا في الفصل
InputManagerService .
وهنا هو mWindowManagerCallbacks في
InputMonitor :
if (appWindowToken != null && appWindowToken.appToken != null) {
دعونا نلقي نظرة فاحصة على inputDispatchingTimedOut (). هنا نعرض فقط الرسالة من خلال ActivityManager عن انتهاء صلاحية المهلة وترك المستخدم يقرر ما إذا كان سيتم إلغاء الإجراء أو الاستمرار في الانتظار. وفي
ActivityManagerService يتم استدعاء AppErrors في حالة التعطل أو ANR.
private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace) { app.crashing = true; app.crashingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); startAppProblemLocked(app); app.stopFreezingAllLocked(); return handleAppCrashLocked(app, shortMsg, longMsg, stackTrace); } private void makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg) { app.notResponding = true; app.notRespondingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, activity, shortMsg, longMsg, null); startAppProblemLocked(app); app.stopFreezingAllLocked(); }
الأسباب الرئيسية لل ANR
- قفل الإدخال / الإخراج
- ازدحام الشبكة
- حظر الصفحات
- حلقة لا نهاية لها
- منطق العمل يستغرق وقتا طويلا
تجنب ANR
- مؤشر ترابط واجهة المستخدم الرئيسية ينفذ المنطق المقترن فقط بواجهة المستخدم ؛
- يتم إجراء العمليات الحسابية المعقدة (على سبيل المثال ، عمليات قواعد البيانات وعمليات الإدخال والإخراج وعمليات الشبكة ، وما إلى ذلك) في دفق منفصل ؛
- استخدم معالج التفاعل بين مؤشر ترابط واجهة المستخدم وسير العمل ؛
- استخدام RxJava الخ للتعامل مع العمليات غير المتزامنة.
كيفية التقاط ANR
ملاحظة: أنشر جميع الاختيارات في قناة التلغراف
@ paradisecurity .