519 Stimmen

Die Anwendung könnte zu viel Arbeit auf ihrem Hauptthread verrichten

Ich bin neu in der Android SDK/API-Umgebung. Es ist das erste Mal, dass ich versuche, ein Diagramm / eine Tabelle zu zeichnen. Ich habe versucht, verschiedene Arten von Beispielscodes auf dem Emulator mit 3 verschiedenen kostenlosen Bibliotheken auszuführen, aber nichts wird auf dem Layout-Bildschirm angezeigt. Im Logcat wird die folgende Meldung wiederholt:

 W/Trace(1378): Unerwarteter Wert von nativeGetEnabledTags: 0
 I/Choreographer(1378): 55 Frames übersprungen! Die Anwendung könnte zu viel Arbeit auf ihrem Hauptthread erledigen.

Das Problem trat nicht auf, und das Diagramm funktionierte, als ich einen Beispielscode für eine Testversion einer lizenzierten Bibliothek ausführte.

585voto

Jorgesys Punkte 119076

Entnommen von : Android UI : Behebung übersprungener Frames

Jeder, der mit der Entwicklung von Android-Anwendungen beginnt, sieht diese Meldung im Logcat "Choreographer(abc): Übersprungene xx Frames! Die Anwendung führt möglicherweise zu viel Arbeit auf ihrem Hauptthread aus." Was bedeutet das eigentlich, warum sollten Sie besorgt sein und wie lässt sich dies lösen.

Das bedeutet, dass Ihr Code lange braucht, um verarbeitet zu werden und Frames übersprungen werden, Es kann sein, dass dies aufgrund von aufwändigen Berechnungen geschieht, die im Herzen Ihrer Anwendung oder beim Zugriff auf die Datenbank oder bei anderen Vorgängen erfolgen, die dazu führen, dass der Thread für eine Weile anhält.

Hier ist eine ausführlichere Erklärung:

Der Choreographer ermöglicht es Apps, sich mit der VSync zu verbinden und Dinge ordnungsgemäß zu timen, um die Leistung zu verbessern.

Android-Ansichtsanimationen verwenden intern ebenfalls den Choreographer zu demselben Zweck: um die Animationen korrekt zu timen und möglicherweise die Leistung zu verbessern.

Da der Choreographer über jedes VSync-Ereignis informiert wird, kann er feststellen, ob eines der Runnables, die über die Choreographer.post* APIs übergeben werden, nicht innerhalb eines Frames beendet wird, was dazu führt, dass Frames übersprungen werden.

Meines Erachtens kann der Choreographer nur das Überspringen von Frames erkennen. Er hat keine Möglichkeit zu erkennen, warum dies passiert.

Die Meldung "Die Anwendung führt möglicherweise zu viel Arbeit auf ihrem Hauptthread aus." könnte irreführend sein.

Quelle : Bedeutung von Choreographer-Meldungen in Logcat

Warum Sie besorgt sein sollten

Wenn diese Meldung im Android-Emulator erscheint und die Anzahl der übersprungenen Frames relativ gering ist (<100), können Sie davon ausgehen, dass der Emulator langsam ist – was fast immer der Fall ist. Aber wenn die Anzahl der übersprungenen Frames groß ist und im Bereich von 300+ liegt, dann gibt es möglicherweise ernsthafte Probleme mit Ihrem Code. Android-Geräte gibt es in einer Vielzahl von Hardwarevarianten im Gegensatz zu iOS- und Windows-Geräten. Der RAM und die CPU variieren und wenn Sie eine vernünftige Leistung und Benutzererfahrung auf allen Geräten wollen, dann müssen Sie das beheben. Wenn Frames übersprungen werden, ist die Benutzeroberfläche langsam und ruckelt, was keine wünschenswerte Benutzererfahrung ist.

Wie man es behebt

Um dies zu beheben, muss man die Stellen identifizieren, an denen eine lange Verarbeitungsdauer auftritt oder auftreten kann. Der beste Weg ist, alle Verarbeitungsschritte, egal ob klein oder groß, in einem Thread durchzuführen, der sich vom Haupt-UI-Thread unterscheidet. Sei es der Zugriff auf Daten aus der SQLite-Datenbank, das Durchführen von komplexen Berechnungen oder das Sortieren eines Arrays – tun Sie dies in einem anderen Thread.

Es gibt jedoch einen Haken: Sie werden einen neuen Thread erstellen, um diese Operationen durchzuführen, und wenn Sie Ihre Anwendung ausführen, wird sie mit der Meldung "Nur der ursprüngliche Thread, der eine View-Hierarchie erstellt hat, kann die Views berühren" abstürzen. Sie müssen wissen, dass die UI in Android nur vom Hauptthread oder dem UI-Thread geändert werden kann. Jeder andere Thread, der versucht, dies zu tun, scheitert und stürzt mit diesem Fehler ab. Was Sie tun müssen, ist, einen neuen Runnable innerhalb von runOnUiThread zu erstellen und innerhalb dieses Runnable sollten alle Operationen, die die UI betreffen, durchgeführt werden. Finden Sie ein Beispiel hier.

Daher haben wir einen Thread und ein Runnable für die Verarbeitung außerhalb des Hauptthreads, gibt es noch etwas? In Android gibt es AsyncTask, mit dem Sie langwierige Prozesse auf dem UI-Thread ausführen können. Dies ist besonders nützlich, wenn Ihre Anwendungen datengesteuert sind, Web-APIs verwenden oder komplexe Benutzeroberflächen wie diejenigen, die mit Canvas erstellt wurden, nutzen. Die Stärke von AsyncTask liegt darin, dass es ermöglicht, Dinge im Hintergrund zu erledigen und sobald die Verarbeitung abgeschlossen ist, können Sie einfach die erforderlichen Aktionen auf der UI durchführen, ohne dass es zu Verzögerungen kommt. Dies ist möglich, da der AsyncTask sich vom Aktivitäts-UI-Thread ableitet – alle Operationen, die Sie über AsyncTask auf der UI durchführen, erfolgen in einem anderen Thread als dem Haupt-UI-Thread, ohne die Benutzerinteraktion zu beeinträchtigen.

Daher wissen Sie nun, was Sie tun müssen, um reibungslose Android-Anwendungen zu erstellen, und soweit ich weiß, bekommt jeder Anfänger diese Meldung auf seiner Konsole angezeigt.

304voto

Sithu Punkte 4121

Wie andere bereits oben geantwortet haben, bedeutet "55 Frames übersprungen!" dass in deiner Anwendung einige intensive Verarbeitungen stattfinden.

In meinem Fall gibt es keine intensive Verarbeitung in meiner Anwendung. Ich habe alles doppelt und dreifach überprüft und die Prozesse entfernt, von denen ich dachte, dass sie etwas zu viel waren.

Ich habe Fragmente, Aktivitäten, Bibliotheken entfernt, bis nur noch das Grundgerüst übrig war. Aber das Problem ging immer noch nicht weg. Ich beschloss, die Ressourcen zu überprüfen und stellte fest, dass einige Icons und Hintergründe, die ich verwende, ziemlich groß sind, da ich die Größe dieser Ressourcen vergessen hatte zu überprüfen.

Also, mein Vorschlag ist, wenn keiner der oben genannten Antworten hilft, können Sie auch die Größe Ihrer Ressourcendateien überprüfen.

75voto

Auch ich hatte das gleiche Problem.
Bei mir handelte es sich um einen Fall, in dem ich ein Hintergrundbild verwendete, das in den Zeichnungen war. Dieses bestimmte Bild hatte etwa 130kB und wurde während des Splash-Screens und der Startseite in meiner Android-App verwendet.

Lösung - Ich habe einfach dieses bestimmte Bild vom Zeichnungen-Ordner in den Zeichnungen-xxx-Ordner verschoben und konnte dadurch viel Speicherplatz freigeben, der im Hintergrund belegt war, und die übersprungenen Frames wurden nicht mehr übersprungen.

Update Verwenden Sie den 'nodp' drawable-Ressourcenordner zur Speicherung von Hintergrund-Zeichnungen.
Wird ein dichtegestützter drawable-Ordner oder drawable-nodpi bevorzugt?

24voto

user1643723 Punkte 3904

Ein weiterer häufiger Grund für Verzögerungen auf dem UI-Thread ist der Zugriff auf SharedPreferences. Wenn Sie zum ersten Mal PreferenceManager.getSharedPreferences und ähnliche Methoden aufrufen, wird die zugehörige .xml-Datei sofort im selben Thread geladen und geparst.

Eine gute Möglichkeit, dieses Problem zu bekämpfen, besteht darin, den ersten Ladevorgang von SharedPreference im Hintergrundthread auszulösen, der so früh wie möglich gestartet wird (z. B. von onCreate Ihrer Anwendungsklasse). Auf diese Weise kann das Preference-Objekt möglicherweise bereits konstruiert sein, wenn Sie es verwenden möchten.

Leider ist es manchmal notwendig, während der frühen Phasen des Startvorgangs auf die SharedPreferences-Dateien zuzugreifen (z. B. in der ersten Aktivität oder sogar in der Anwendung selbst). In solchen Fällen ist es immer noch möglich, das UI nicht zu blockieren, indem MessageQueue.IdleHandler verwendet wird. Führen Sie alle anderen Operationen, die auf dem Hauptthread ausgeführt werden müssen, durch, installieren Sie dann den IdleHandler, um den Code auszuführen, nachdem Ihre Aktivität vollständig gezeichnet wurde. In diesem Runnable sollten Sie in der Lage sein, auf SharedPreferences zuzugreifen, ohne zu viele Zeichenoperationen zu verzögern und den Choreographen unglücklich zu machen.

22voto

phen0menon Punkte 2149

Ich hatte dasselbe Problem. Der Android-Emulator funktionierte einwandfrei auf Android < 6.0. Als ich den Emulator Nexus 5 (Android 6.0) verwendete, lief die App sehr langsam mit I/Choreographer: Übersprungene Frames in den Logs.

Also habe ich dieses Problem gelöst, indem ich in der Manifestdatei die Option hardwareAccelerated auf true

        ...

Aktualisierung Jan 2022. Gemäß dem Kommentar von @M.Ed: Die Hardwarebeschleunigung ist standardmäßig aktiviert, wenn Sie APIs >= 14 anvisieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X