App responsiv halten

Abbildung 1: Ein ANR-Dialogfeld, das dem Nutzer angezeigt wird.

In diesem Dokument wird beschrieben, wie das Android-System bestimmt, ob eine App nicht reagiert, und wie du dafür sorgen kannst, dass deine App responsiv bleibt.

Unabhängig davon, wie gut Ihr Code geschrieben ist, kann es passieren, dass Ihre Anwendung sich langsam anfühlt, sich aufhängt, für längere Zeit einfriert oder die Verarbeitung von Eingaben zu lange dauert. Wenn Ihre App im Vordergrund ausgeführt wird und nicht reagiert, wird das Dialogfeld „App antwortet nicht“ angezeigt, wie in Abbildung 1 dargestellt. Über das ANR-Dialogfeld kann der Nutzer das Beenden der App erzwingen. Wenn sich die App nicht im Vordergrund befindet, wird sie automatisch angehalten. Es ist wichtig, dass Sie die Reaktionsschnelligkeit Ihrer App so gestalten, dass ANR-Dialogfelder minimiert werden.

ANR-Trigger

Im Allgemeinen zeigt das System einen ANR-Fehler an, wenn eine Anwendung nicht auf Nutzereingaben im Hauptthread – auch UI-Thread genannt – reagieren kann. Dadurch wird verhindert, dass das System eingehende Nutzereingabeereignisse verarbeitet.

Ein ANR-Fehler kann beispielsweise auftreten, wenn eine Anwendung einen blockierenden E/A-Vorgang wie den Netzwerkzugriff im UI-Thread ausführt. Ein weiteres Beispiel: Eine Anwendung verbringt zu viel Zeit damit, eine komplexe In-Memory-Struktur zu erstellen oder den nächsten Schritt in einem Spiel im UI-Thread zu berechnen.

Bei Android wird die Reaktionszeit von Apps von den Systemdiensten ActivityManager und WindowManager überwacht. Android zeigt das ANR-Dialogfeld für eine App an, wenn eine der folgenden Bedingungen erkannt wird:

  • Keine Reaktion auf ein Eingabeereignis (z. B. Tastendruck oder Bildschirmberührungen) innerhalb von 5 Sekunden.
  • Die Ausführung eines BroadcastReceiver bei Intents im Vordergrund wird nach 10 bis 20 Sekunden nicht abgeschlossen. Weitere Informationen findest du unter Zeitüberschreitung beim Sendeempfänger.

ANR-Fehler vermeiden

Im Folgenden finden Sie allgemeine Tipps zur Vermeidung von ANR-Fehlern. Weitere Informationen zur Diagnose und Fehlerbehebung verschiedener Arten von ANR-Fehlern finden Sie auf den anderen Seiten in diesem Abschnitt.

  • Sie können die Blockierung des Hauptthreads jederzeit aufheben und Threads strategisch einsetzen.

    • Führen Sie im Hauptthread der Anwendung keine blockierenden oder lang andauernden Vorgänge aus. Erstellen Sie stattdessen einen Worker-Thread und erledigen Sie die meiste Arbeit dort.

    • Versuchen Sie, Konflikte durch Sperren zwischen dem Hauptthread und anderen Threads so gering wie möglich zu halten.

    • Minimieren Sie alle Arbeiten im Hauptthread, die nicht mit der UI zusammenhängen, z. B. bei der Verarbeitung von Broadcasts oder dem Ausführen von Diensten. Jede Methode, die im UI-Thread ausgeführt wird, muss so wenig Arbeit wie möglich damit ausführen. Insbesondere müssen Aktivitäten so wenig wie möglich in wichtigen Lebenszyklusmethoden wie onCreate() und onResume() eingerichtet werden. Weitere Informationen zu verfügbaren Lösungen für die Planung der Arbeit an einem Hintergrundthread und die Kommunikation mit der UI finden Sie unter Hintergrundarbeit – Übersicht.

    • Seien Sie vorsichtig, wenn Sie Threadpools zwischen Komponenten teilen. Verwenden Sie nicht dieselben Threads für potenziell lange blockierende Vorgänge und zeitkritische Aufgaben wie den Empfang von Rundsendungen.

  • Schneller Start von Apps Minimieren Sie langsame oder blockierende Vorgänge im Startcode der Anwendung, z. B. Methoden, die während der Dolchinitialisierung ausgeführt werden.

  • Wenn Sie BroadcastReceiver verwenden, sollten Sie Übertragungsempfänger mit Context.registerReceiver in einem Nicht-Hauptthread ausführen. Weitere Informationen findest du unter ANRs in BroadcastReceiver.

ANR-Fehler in BroadcastReceiver

Die Ausführungszeit für BroadcastReceiver ist begrenzt, da Übertragungsempfänger kleine, diskrete Aufgaben im Hintergrund ausführen, z. B. das Speichern einer Einstellung oder das Registrieren einer Notification. Wie bei anderen Methoden, die im UI-Thread aufgerufen werden, müssen Anwendungen also potenziell lang andauernde Vorgänge oder Berechnungen in einem Broadcast-Empfänger vermeiden. Anstatt lang andauernde Aufgaben über den UI-Thread auszuführen, sollten Sie sie zur späteren Ausführung im Hintergrund ausführen. Weitere Informationen zu möglichen Lösungen finden Sie unter Überblick über Hintergrundarbeiten.

Ein weiteres häufiges Problem mit BroadcastReceiver-Objekten tritt auf, wenn sie zu häufig ausgeführt werden. Eine häufige Ausführung im Hintergrund kann den für andere Apps verfügbaren Arbeitsspeicher reduzieren. Weitere Informationen zum effizienten Aktivieren und Deaktivieren von BroadcastReceiver-Objekten finden Sie unter Broadcasts – Übersicht.

Reaktionsschnelligkeit stärken

Im Allgemeinen ist 100 bis 200 ms der Grenzwert, über den Nutzer die Langsamkeit einer App wahrnehmen. Hier sind weitere Tipps, wie Sie dafür sorgen, dass Ihre App auf Nutzer reagiert:

  • Wenn Ihre App als Reaktion auf Nutzereingaben im Hintergrund arbeitet, zeigen Sie den Fortschritt an, z. B. mit einem ProgressBar in Ihrer UI.

  • Führen Sie insbesondere bei Spielen Berechnungen für Verschiebungen in einem Worker-Thread durch.

  • Wenn die Ersteinrichtung Ihrer App zeitaufwendig ist, empfiehlt es sich, einen Ladebildschirm einzublenden oder die Hauptansicht so schnell wie möglich zu rendern. Zeigt an, dass der Ladevorgang läuft, und füllt die Informationen asynchron. In beiden Fällen sollten Sie angeben, dass Fortschritte gemacht werden, damit der Nutzer nicht wahrnimmt, dass die Anwendung eingefroren ist.

  • Mit Leistungstools wie Perfetto und CPU Profiler können Sie Engpässe bei der Reaktionsgeschwindigkeit Ihrer App ermitteln.