Wie kann ich langsame Android Apps optimieren und somit ein besseres Nutzererlebnis schaffen?
Die Leistung ist ein kritischer Aspekt bei der Android-Entwicklung, da sie die Benutzererfahrung und -bindung erheblich beeinflussen kann. Benutzer erwarten, dass Anwendungen schnell, reaktionsschnell und effizient sind. Eine schlechte Performance kann zu Deinstallationen und negativen Bewertungen führen. In diesem Artikel werden verschiedene Techniken und Best Practices zur Optimierung der Android App Performance untersucht, um ein reibungsloses und effizientes Nutzererlebnis zu gewährleisten.
Inhaltsverzeichnis
Leistungsmetriken verstehen
Bevor die Optimierungstechniken vorgestellt und erklärt werden, ist es wichtig, einige grundlegende Performance-Metriken für Android-Apps zu verstehen:
App-Startzeit
Diese Metrik misst die Zeit, die die App benötigt, um nach dem Tippen auf das App-Symbol für die Interaktion bereit zu sein. Schnellere Startzeiten verbessern den ersten Eindruck und die Benutzerzufriedenheit. Darüber hinaus gibt es zwei Möglichkeiten, wie eine App gestartet werden kann:
Kaltstart: Wenn die App von Grund auf neu gestartet wird
Warmstart: Wenn die App aus dem Hintergrundzustand gestartet wird
Bildwiederholrate
Eine konstante Bildwiederholrate (typischerweise 60 Bilder pro Sekunde) sorgt für flüssige Animationen und Übergänge. Eine Verringerung der Bildwiederholrate kann zu einer stotternden oder ruckelnden Benutzeroberfläche führen, was sich negativ auf die Benutzererfahrung auswirkt.
Speichernutzung
Eine effiziente Speichernutzung verhindert Abstürze und verbessert die Stabilität der Anwendung. Eine übermäßige Speichernutzung kann zu OutOfMemoryErrors führen, welche die Anwendung zum Absturz bringen.
Batterieverbrauch
Die Minimierung des Batterieverbrauchs ist entscheidend für die Benutzerzufriedenheit. Ein hoher Batterieverbrauch kann dazu führen, dass Benutzer die App deinstallieren, da die Ressourcen des Endgeräts nicht effizient genutzt werden.
Netzwerkeffizienz
Die Optimierung des Netzwerkverkehrs reduziert die Datennutzung und beschleunigt die Datenabfrage. Eine effiziente Netzwerknutzung ist entscheidend für die Leistung und das Nutzererlebnis, insbesondere in Regionen mit eingeschränkter Konnektivität.
Profiling Tools in Android Studio
Android Studio bietet mehrere integrierte Tools, um die Leistung Ihrer App zu profilieren und zu überwachen:
Android Profiler
Liefert Echtzeitdaten zur CPU-, Speicher-, Netzwerk- und Energienutzung. Dieses Tool kann verwendet werden, um Leistungsengpässe zu identifizieren und entsprechend zu optimieren.
CPU-Profiler: Analyse der CPU-Nutzung und Thread-Aktivitäten
Speicher-Profiler: Überwachung der Speicherzuweisung und -freigabe
Netzwerk-Profiler: Beobachtung der gesendeten und empfangenen Daten
Energie-Profiler: Überprüfung des Batterieverbrauchs
Systrace
Erfasst detaillierte Informationen zur Ablaufverfolgung, die zur Analyse der Anwendungsleistung verwendet werden können. Dies hilft bei der Identifizierung von Problemen mit der UI-Darstellung, Übergängen und anderen UI-Eigenschaften.
LeakCanary
Eine Bibliothek zur Erkennung von Speicherlecks (Memory Leaks) in der Anwendung. Diese Bibliothek kann zur automatischen Erkennung von Speicherlecks während der Entwicklung und des Testens verwendet werden und erleichtert die Behebung von Memory Leaks.
Firebase Performance Monitoring
Bietet Echtzeitdaten zur Benutzerleistung. Es gibt Aufschluss über die Startzeit der Anwendung, die Zeit für den Netzwerkzugriff und vieles mehr. Außerdem kann es Entwickler:innen helfen, Leistungsprobleme in der Produktion zu erkennen und zu beheben. Allerdings sollte auch der Aspekt des Datenschutzes berücksichtigt werden.
Verbesserung der App-Startzeit
Um die Startzeit der Anwendung zu verkürzen, sollten die folgenden Strategien in Betracht gezogen werden:
Optimierung des Splash-Screens
Es wird empfohlen, einen „leichten“ Startbildschirm zu verwenden, um den Start der Anwendung effizient zu gestalten. Rechenintensive Berechnungen und komplexe Ressourcenzugriffe sollten beim Start vermieden werden. Außerdem sollte darauf geachtet werden, dass der Startbildschirm nur für eine minimale Zeit angezeigt wird, die gerade ausreicht, um den Eindruck eines schnellen Starts zu vermitteln.
Lazy Initialization
Die Initialisierung nicht essenzieller Komponenten sollte auf einen Zeitpunkt nach dem Start der Anwendung verschoben werden. Dadurch wird die anfängliche Ladezeit verkürzt.
Verwendung von Coroutines
Zeitintensive Aufgaben und Berechnungen sollten außerhalb des Mainthreads ausgeführt werden, um die Reaktionsfähigkeit der UI zu erhalten. Unter Android werden dafür Coroutines verwendet, um asynchrone Aufgaben effizient abzuarbeiten.
Verbesserung der UI-Leistung
Eine flüssige und reaktionsschnelle Benutzeroberfläche ist entscheidend für eine gute Benutzererfahrung. Diese Techniken können helfen, die Performance von Android Apps zu verbessern:
Layout-Hierarchie-Optimierung
Die Tiefe der View-Hierarchie sollte minimiert werden, um die Rendering-Geschwindigkeit zu verbessern. Werkzeuge wie der Layout Inspector können verwendet werden, um Layouts zu analysieren und zu optimieren.
Vermeidung von Overdraw
Dazu können Werkzeuge wie das Overdraw Debug Tool verwendet werden, um den sogenannten „Overdraw“ zu erkennen und zu beseitigen. Overdraw tritt auf, wenn derselbe Pixel mehrmals gezeichnet wird und dadurch GPU-Ressourcen verschwendet werden.
Die Overdraw-Debugging-Optionen können in den Entwickleroptionen aktiviert werden und für die Optimierung von Layouts verwendet werden, um Overdraw zu reduzieren.
Effiziente Bitmap-Verarbeitung
Geeignete Bitmap- oder Vektorgrafikgrößen sowie Caching-Mechanismen sollten verwendet werden, um Speicherprobleme zu vermeiden und die UI performant zu halten. Da Bilder in fast jeder mobilen Anwendung verwendet werden, ist dies ein Faktor, der in Bezug auf die Leistung optimiert werden kann.
Speicherverwaltung
Ein effektives Speichermanagement kann Abstürze verhindern und die Leistung verbessern:
Vermeidung von Speicherlecks (Memory Leaks)
Werkzeuge wie LeakCanary können verwendet werden, um Memory Leaks zu erkennen und zu beheben. Häufige Quellen für Memory Leaks sind statische Referenzen auf den Kontext und persistente Objekte, die Referenzen halten. Auch Singleton-Instanzen sollten hier analysiert und überwacht werden.
Effiziente Verwendung von Collections
Die Verwendung der richtigen Datenstrukturen für die gewünschten Bedürfnisse ist ein wichtiger Faktor bei der Programmierung. So haben z.B. Arrays oder Listen andere Eigenschaften und damit Vor- und Nachteile gegenüber Maps (z.B. HashMap).
Caching-Strategien
Es gibt verschiedene Ansätze für Caching-Strategien. Jede hat ihre eigenen Vor- und Nachteile. Die wichtigsten sind:
- Memory Caching
- Disk Caching
- Networking Caching
Reduzierung des Batterieverbrauchs
Damit die Anwendung ressourcenschonend und damit performant ausgeführt werden kann, sollten folgende Punkte berücksichtigt werden:
Optimierung der Hintergrundprozesse
Um Hintergrundaufgaben unter Android effizient zu verwalten, wird der „WorkManager“ eingesetzt. Der WorkManager sorgt dafür, dass Hintergrundaufgaben auf Basis der Systembedingungen optimiert ausgeführt werden.
Minimierung oder Vermeidung von Wake Locks
Es sollte darauf geachtet werden, dass das Gerät bei Nichtbenutzung in einen Schlafmodus (Stichworte: Doze Mode oder App Standby) wechseln kann. Wake Locks sollten sparsam eingesetzt oder wenn möglich vermieden werden, da sie die App am Leben erhalten können.
Effiziente Standortdienste
Geofencing und Standortaktualisierungen in Batches sollten verwendet werden, um den Batterieverbrauch zu reduzieren. Die Häufigkeit der Standortaktualisierungen sollte begrenzt werden.
Netzwerkleistung
Die Optimierung der Netzwerknutzung kann die Leistung der Anwendung erheblich verbessern. Dies geht jedoch Hand in Hand mit einem möglichst leistungsfähigen Server:
Optimierung der API-Aufrufe
Die Anzahl der Netzwerkanfragen sollte auf ein Minimum reduziert werden, z.B. durch Batch-Abfragen oder sogar durch Vorladen der Daten.
Verwendung von Caching
Hier kann auch eine HTTP-Caching-Strategie angewendet werden, um redundante Netzwerkanfragen zu reduzieren. Retrofit und OkHttp (gängige Bibliotheken unter Android) unterstützen Caching von Haus aus.
Code-Optimierungstechniken
Neben all diesen Optimierungstechniken spielt auch eine saubere und effiziente Programmierung der Anwendung eine wichtige Rolle. Folgende Techniken können dabei helfen:
Vermeidung unnötiger Objekterstellung
Wenn möglich, sollten Objekte wiederverwendet werden, um den Overhead der Garbage Collection zu reduzieren. Die Erzeugung von Objekten und die Garbage Collection können die Performance beeinträchtigen, insbesondere in Schleifen oder häufig aufgerufenen Methoden.
Optimierung von Schleifen und Algorithmen
Unnötige Berechnungen sollten vermieden und die Komplexität der Algorithmen reduziert werden.
Dieses Beispiel soll verdeutlichen, dass beide Funktionen zwar zum gleichen Ergebnis führen, die Berechnung aber unterschiedlich durchgeführt werden kann. Der Fokus liegt hier explizit auf Codeästhetik, Lesbarkeit und Verständlichkeit. Ein Benchmark, welche Funktion die Berechnung tatsächlich schneller durchführt, wurde hier nicht berücksichtigt.
Vermeidung von Reflection
Reflection ist flexibel, aber langsam. Alternativen wie direkte Methodenaufrufe oder das Factory-Pattern sollten wenn möglich in Betracht gezogen werden.
Zugriff auf Funktionen mittels Reflection:
Direkter Zugriff:
Warum Reflection vermeiden?
- Leistungsprobleme: Reflection ist langsamer, da es zur Laufzeit viele zusätzliche Prüfungen und Operationen durchführt.
- Fehlende Typensicherheit: Reflection umgeht die Typprüfung zur Kompilierzeit, was zu Laufzeitfehlern führen kann.
- Schwierig zu debuggen: Fehler in Code, der Reflection verwendet, sind oft schwieriger zu diagnostizieren und zu beheben.
- Verlust von Optimierungen: Der Compiler kann Reflection-Code nicht so effizient optimieren wie normalen Code.
ProGuard und R8
Code Shrinking- und Obfuscation-Tools wie ProGuard und R8 können verwendet werden, um die Größe der APK oder des App Bundles zu reduzieren und den Bytecode zu optimieren. Diese Tools entfernen unnötigen Code, benennen Klassen und Methoden um, um sie kürzer zu machen, und optimieren den Bytecode für eine bessere Leistung.
Fazit
Die Optimierung der Android App Performance ist entscheidend, um eine akzeptable Benutzererfahrung zu bieten und die Benutzer:innen zu halten. Das Verstehen von Leistungsmetriken, die Verwendung von Profiling Tools und die Implementierung von Optimierungstechniken wie die Verbesserung der App-Startzeit, die Verbesserung der UI-Performance, die effiziente Speicherverwaltung, die Reduzierung des Akkuverbrauchs, die Optimierung der Netzwerknutzung und die Code-Optimierung können zu flüssigeren, reaktionsschnelleren und effizienteren Apps führen, welche die User gerne verwenden. Dabei ist zu beachten, dass die Leistungsoptimierung ein kontinuierlicher Prozess ist. Daher sollte die Leistung der Anwendung auch nach dem Launch weiter überwacht und gegebenenfalls optimiert werden.
Quellen:
- https://developer.android.com/topic/performance/overview
- https://developer.android.com/studio/profile
- https://developer.android.com/topic/libraries/architecture/workmanager