ANR (Anwendung antwortet nicht) - Ein Fehler, der auftritt, wenn die Anwendung nicht antwortet. Infolgedessen wird ein Dialogfeld geöffnet, in dem der Benutzer aufgefordert wird, die Anwendung zu warten oder zu schließen.

ANR-Bedingungen
- Eingabeereignisse (Tasten und Berührungsereignisse) werden 5 Sekunden lang nicht verarbeitet.
- BroadcastReceiver (onRecieve ()) wurde nicht innerhalb der angegebenen Zeit verarbeitet (Vordergrund - 10 s, Hintergrund - 60 s);
- ContentProvider nicht innerhalb von 10 Sekunden abgeschlossen.
Normalerweise ist der Haupt-Thread blockiert.
Wenn Sie meine Artikel lesen, sind Sie wahrscheinlich bereits daran gewöhnt, dass wir in den Quellcode kriechen. Mal sehen, wie der
ANR unter der Haube aussieht.
Die
AppErrors- Klasse
behandelt nicht nur ANR, sondern auch andere Fehler, die in der Anwendung auftreten können, einschließlich Absturz. Die handleShowAnrUi () -Methode öffnet gerade dieses beängstigende Fenster für viele Entwickler und Benutzer, in dem ANR angezeigt wird.
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 startet hier jedoch nicht. Wie ich oben sagte, ist eine der ersten Ursachen für diesen Fehler die Verzögerung des Eingabeereignisses, die 5 Sekunden beträgt. Durch eine kurze Suche können wir herausfinden, wo dieser Wert eingestellt ist.
namespace android {
Jetzt können wir in den Code schauen, in dem der native Teil aufgerufen wird. Dies geschieht in der Klasse
InputManagerService .
Und hier sind die mWindowManagerCallbacks im
InputMonitor :
if (appWindowToken != null && appWindowToken.appToken != null) {
Schauen wir uns inputDispatchingTimedOut () genauer an. Hier zeigen wir einfach die Nachricht über den ActivityManager über den Ablauf des Timeouts und lassen den Benutzer entscheiden, ob die Aktion abgebrochen oder weiter gewartet werden soll. Und im
ActivityManagerService wird AppErrors im Falle eines Absturzes oder einer ANR aufgerufen.
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(); }
Die Hauptursachen von ANR
- Eingangs- / Ausgangssperre
- Überlastung des Netzwerks
- Fadenblockierung
- Endlosschleife
- Geschäftslogik dauert zu lange
ANR vermeiden
- Der Hauptthread der Benutzeroberfläche führt eine Logik aus, die nur der Benutzeroberfläche zugeordnet ist.
- Komplexe Berechnungen (z. B. Datenbankoperationen, Eingabe-Ausgabe-Operationen, Netzwerkoperationen usw.) werden in einem separaten Stream ausgeführt.
- Verwenden Sie den Handler, um zwischen dem Benutzeroberflächenthread und dem Workflow zu interagieren.
- Verwenden Sie RxJava usw. asynchrone Operationen zu behandeln.
Wie man ANR fängt
PS Ich veröffentliche alle Auswahlen im Telegrammkanal
@paradisecurity .