Eine langsame App ist der Hauptgrund, warum Benutzer Programme deinstallieren. Millisekunden Verzögerung beim Start oder beim Scrollen einer Liste reduzieren die Bindung um Dutzende Prozent. Leistung (Performance) ist nicht nur Geschwindigkeit, sondern auch Stabilität: keine ANR, Abstürze oder Speicherlecks. Dieser Artikel behandelt alle Aspekte der Leistung: von der Speicherverwaltung (GC, ARC) bis zur Profilerstellung mit Tools. Mehr erfahren Sie im offiziellen Android Performance-Leitfaden.
Das Wichtigste
Die App-Leistung hängt direkt mit Ruckeln (Jank) zusammen — einer merklichen Verzögerung zwischen Benutzeraktion und UI-Reaktion. Hauptursachen: Blockieren des Hauptthreads (schwere Operationen im UI-Thread), häufige Layout-Neuzeichnungen (Overdraw), Speicherlecks (häufiger GC), nicht optimale Algorithmen (O(n²) bei großen Datenmengen). Bildrate (FPS) — Anzahl der Bilder pro Sekunde. Für eine komfortable Erfahrung werden stabile 60 FPS (Android) oder 120 FPS (iPhone Pro, iPad Pro) benötigt. VSync synchronisiert das Rendering mit der Bildwiederholfrequenz des Bildschirms.
Jank tritt auf, wenn das Rendern eines einzelnen Bildes 16,6 ms (für 60 FPS) oder 8,3 ms (für 120 FPS) überschreitet. Die GPU-Profilerstellung (Profile GPU Rendering auf Android, Core Animation auf iOS) zeigt, welche Renderphasen am meisten Zeit in Anspruch nehmen. Hauptphasen: Layout (Positionierung der Elemente), Draw (Zeichnen), Display (Übertragung in den Bildpuffer). Das häufigste Problem ist die Layout-Inflation in XML, insbesondere bei komplexen verschachtelten ConstraintLayouts.
Time-to-Interactive (TTI) — die Zeit, die die App benötigt, um vollständig interaktionsbereit zu sein. TTI umfasst Cold Start, Datenladen und Bibliotheksinitialisierung. Google empfiehlt TTI unter 5 Sekunden, Apple — unter 2 Sekunden für Hauptbildschirme. Lazy Loading — Technik des verzögerten Ladens von Inhalten und Bibliotheken, entscheidend für die Verbesserung von TTI. Bei IT Sectr verwenden wir standardmäßig faule Initialisierung in allen Projekten.
ANR und Abstürze sind die Hauptfeinde der Leistung mobiler Apps. ANR (Application Not Responding) — Dialogfeld auf Android, das erscheint, wenn der Hauptthread länger als 5 Sekunden blockiert ist. Ursachen: synchrone Netzwerkanfragen im UI-Thread, Datenbankarbeit ohne Coroutinen, große Bitmap-Dekodierung ohne Downsampling, Deadlock im Hauptthread. Der ANR-Aufrufstack wird in /data/anr/traces.txt gespeichert und ermöglicht die genaue Bestimmung der Blockierungsstelle.
Absturz — unerwartetes Beenden der App. Auf Android — eine Exception (Java/Kotlin) oder ein Signal (nativer Code). Auf iOS — NSException oder Signal (EXC_BAD_ACCESS — Zugriff auf freigegebenen Speicher). Crash-Reporting-Tools: Firebase Crashlytics, Sentry, BugSnag. Sie sammeln Stacktrace, Gerätedaten und Reproduktionsschritte. Stack Overflow — Überlauf des Aufrufstapels durch endlose Rekursion. OutOfMemoryError — wenn der Heap voll ist.
StrictMode — Android-Tool zur Erkennung von Thread-Sicherheitsverletzungen. Es ermöglicht das Festlegen von Regeln: ThreadPolicy (Festplatte/Netzwerk im Hauptthread verbieten), VmPolicy (Activity-, SQLite-, CloseGuard-Lecks erkennen). StrictMode sollte nur im Debug-Build aktiviert werden — im Release sollte es nicht laufen. Das iOS-Äquivalent ist der Main Thread Checker (Xcode), der automatisch UIKit-Aufrufe erkennt, die nicht im Hauptthread erfolgen.
Ein Speicherleck (Memory Leak) ist eine Situation, in der ein Objekt im Speicher bleibt, obwohl die App es nicht mehr verwendet. Dies verringert direkt die App-Leistung. Auf Android kann GC (Garbage Collection) ein Objekt nicht sammeln, wenn eine starke Referenz darauf besteht. Typische Ursachen: statische Referenzen auf Activity, nicht gelöschte Callbacks/Beobachter, innere Klassen mit implizitem Verweis auf die äußere Klasse, Handler mit nicht gelöschten Nachrichten. LeakCanary — Bibliothek zur automatischen Leckerkennung.
ARC (Automatic Reference Counting) — Speicherverwaltungsmodell in iOS. Jedes Objekt hat einen Referenzzähler (Retain Count). Wenn der Zähler null erreicht, wird der Speicher freigegeben. Ein Retain Cycle tritt auf, wenn zwei Objekte starke Referenzen aufeinander halten (A → B und B → A). ARC wird die Zähler niemals auf null setzen. Lösung: schwache Referenzen (weak) oder herrenlose (unowned). Weak wird automatisch auf nil gesetzt, wenn das Objekt freigegeben wird. Unowned wird nicht auf nil gesetzt, garantiert aber, dass das Objekt lebt.
GC (Garbage Collection) läuft auf Android (Java/Kotlin). GC pausiert regelmäßig die Ausführung (Stop-the-World-Pause), um unerreichbare Objekte zu finden und freizugeben. GC-Trigger: wenn der Heap einen bestimmten Füllungsgrad erreicht. ARC läuft auf iOS (Swift/Objective-C) und hat keine Pausen — die Zähler werden bei jeder Zuweisung atomar aktualisiert. ARC ist vorhersagbarer, kann aber bei hoher Zuweisungshäufigkeit übermäßige Retain/Release-Operationen anhäufen.
Schwache Referenz (Weak Reference) und starke Referenz (Strong Reference) — der Referenztyp bestimmt, ob GC/ARC das Objekt freigeben kann. Strong Reference — das Objekt wird nicht gesammelt, solange diese Referenz existiert. Weak Reference — GC/ARC kann das Objekt sammeln; die schwache Referenz wird nil (in Swift/Java WeakReference). Unowned Reference (Swift) — wird bei Freigabe nicht auf nil gesetzt; der Zugriff darauf nach dem Tod des Objekts verursacht einen Absturz. Auf Android wird java.lang.ref.WeakReference für schwache Referenzen verwendet.
Beispiel für die Erkennung eines Lecks auf Android mit LeakCanary:
// Утечка: анонимный класс держит ссылку на Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
// Используем `this@MainActivity`, сохраняя ссылку на Activity
Log.d("TAG", "Handler received message")
}
}
handler.sendEmptyMessageDelayed(0, 60000)
}
}
// Исправление: статический Handler + WeakReference
class SafeHandler(activity: MainActivity) : Handler() {
private val weakActivity =
WeakReference(activity)
override fun handleMessage(msg: Message) {
weakActivity.get() ?: return
Log.d("TAG", "Handler received message")
}
}
Profiling ist der Prozess der Messung der App-Leistung: CPU, Speicher, Netzwerk, Energieverbrauch. Ohne Profiling ist blinde Optimierung nutzlos — Sie wissen nicht, welcher Code-Teil tatsächlich langsam ist.
| Tool | Plattform | Misst | Wann verwenden |
|---|---|---|---|
| Instruments (Time Profiler) | iOS | CPU, Funktionsaufrufe, Ausführungszeit | Algorithmusoptimierung, Engpasssuche |
| Instruments (Allocations) | iOS | Speicher, Objektanzahl, Retain Counts | Suche nach Lecks und übermäßigem Speicherverbrauch |
| Instruments (Leaks) | iOS | Retain Cycles, Speicherlecks | Regelmäßige Prüfung vor dem Release |
| Android Profiler (CPU) | Android | CPU-Auslastung, Thread-Aktivität, Traces | Suche nach Blockaden des Hauptthreads |
| Android Profiler (Memory) | Android | Heap-Dump, Zuweisungsverfolgung | Suche nach Lecks, Objektanalyse |
| Android Profiler (Network) | Android | Verkehr, Geschwindigkeit, Anforderungszeiten | Optimierung von Netzwerkaufrufen |
| LeakCanary | Android | Automatische Erkennung von Speicherlecks | In allen Entwicklungsphasen |
| StrictMode | Android | Festplatte/Netzwerk im Hauptthread, Lecks | Debug-Build |
| Traceview / Systrace | Android | Methodenverfolgung, Systemereignisse | Tiefgehende Latenzanalyse |
Instruments (Xcode) — das leistungsstärkste Tool für iOS. Time Profiler zeigt, welche Funktionen am meisten CPU verbrauchen. Allocations verfolgt die Erstellung und Freigabe von Objekten. Leaks findet automatisch Retain Cycles. Profiling-Schritte: (1) Instruments starten; (2) Vorlage auswählen (Time Profiler für CPU); (3) problematisches Szenario ausführen; (4) Aufrufstack analysieren — die breiteste Spalte ist die "heißeste" Funktion.
Android Profiler ist in Android Studio integriert (View → Tool Windows → Profiler). CPU Profiler zeigt die Auslastung jedes Threads. Memory Profiler — Heap-Dump und Zuweisungsverfolgung. Network Profiler — alle HTTP-Anfragen mit Zeitangaben. Energy Profiler — Energieverbrauch: WakeLock, Location, Network. Für detaillierte Ablaufverfolgung wird Systrace (Android 10+) oder Perfetto verwendet — System-Tracing mit Mikrosekundengenauigkeit.
Der App-Start ist einer der wichtigsten Leistungsindikatoren. Er wird in drei Typen unterteilt: Cold Start — die App wird von Grund auf gestartet: Prozess wird erstellt, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), Klassen laden, Bibliotheken initialisieren. Warm Start — der Prozess existiert, aber die Activity/ViewController wurde zerstört (z. B. bei Bildschirmdrehung oder Rückkehr aus dem Speicher). Hot Start — Activity/ViewController ist im Speicher, die App wird einfach angezeigt (Umschalten von einer anderen App).
Cold Start ist die wichtigste Metrik. Auf Android umfasst er: (1) Launch Activity — XML-Laden, View-Initialisierung; (2) erstes Bild — Zeit bis zur ersten Darstellung. Google empfiehlt: Launch Activity < 200 ms, erstes Bild < 500 ms, TTI < 5 Sekunden. Cold-Start-Optimierung: Application.onCreate reduzieren (Coroutinen für faule Initialisierung), SplashScreen API (Android 12+) verwenden, Bibliotheksinitialisierung verschieben (WorkManager, DI), unnötige ContentProviders entfernen.
Auf iOS umfasst der Cold Start: Laden der Mach-O-Binärdatei, dyld (dynamischer Linker), Initialisierung der Objective-C-Laufzeitumgebung, Application Delegate, erster Controller. Chrome Custom Tabs (Android) und Universal Links (iOS) — Technologien zum schnellen Öffnen externer Inhalte in der App ohne vollständigen Cold Start. Es wird empfohlen, Cold Start auf echten Mittelklassegeräten zu testen.
Die App-Größe ist ein Leistungsfaktor für Installation und Updates. Sie beeinflusst die Konversion: alle 10 MB reduzieren die Konversion um 1%. Google Play empfiehlt APK-Größe unter 150 MB; App Store — unter 200 MB (Mobilfunknetze — 100 MB). Wichtigste Optimierungsmethoden: Bildkompression (WebP statt PNG spart 25-35%), Vektorisierung (VectorDrawable auf Android, SF Symbols auf iOS), Entfernung von ungenutztem Code (R8/ProGuard), Entfernung ungenutzter Ressourcen (lint → unused resources).
App Bundle (Android) — ein Veröffentlichungsformat, bei dem Google Play eine optimierte APK für jedes Gerät generiert. App Bundle reduziert die Download-Größe um 20-40%. Dynamic Delivery — Module, die bei Bedarf heruntergeladen werden (On-Demand Feature Modules). Das iOS-Äquivalent sind On-Demand Resources (ODR): Ressourcen, die nach dem ersten Start heruntergeladen werden (Spiel-Level, Videos).
Lazy Loading — eine Technik, bei der Module und Bibliotheken nicht beim Start geladen werden, sondern bei Bedarf nachgeladen werden. Split APK (Android) und App Slicing (iOS) — Aufteilung der App in Architektur-Slots: arm64-v8a, x86_64. App-Größenoptimierung — ein fortlaufender Prozess: Analysieren Sie die APK-Zusammensetzung (Analyze APK in Android Studio), entfernen Sie doppelte Symbole, verwenden Sie SVG anstelle mehrerer PNG-Dichten. Bei IT Sectr binden wir die Build-Größenprüfung für jeden MR in CI/CD ein.
Häufig gestellte Fragen
ANR (Application Not Responding) — ein Dialog, der auf Android erscheint, wenn der Hauptthread länger als 5 Sekunden blockiert ist. Um ANR zu vermeiden, verlagern Sie alle schweren Operationen (Netzwerk, Datenbank, Dateiverarbeitung) in Hintergrundthreads. Das iOS-Äquivalent ist frozen UI, wenn die App nicht mehr auf Berührungen reagiert.
Ein Speicherleck tritt auf, wenn ein Objekt nicht freigegeben werden kann, weil noch Referenzen darauf existieren. Ein Retain Cycle ist eine Situation in iOS/Objective-C, in der zwei Objekte aufeinander verweisen (A → B → A) und ARC keines freigeben kann. Lösung: weak/unowned-Referenzen und rechtzeitige Bereinigung von Callbacks.
Für iOS: Instruments (Time Profiler, Allocations, Leaks). Für Android: Android Profiler (CPU, Memory, Network), LeakCanary (Speicherlecks), StrictMode (Thread-Verstöße). Es wird empfohlen, das Profiling während der Entwicklung und Integration zu kombinieren.
Cold Start — die App wird von Grund auf gestartet: Prozess erstellt, Klassen geladen, Application.onCreate ausgeführt. Warm Start — der Prozess existiert, aber die Activity/ViewController wird neu erstellt. Hot Start — Activity/ViewController ist bereits im Speicher, wird einfach angezeigt. Cold Start ist am langsamsten (1-5 Sekunden) und für die Benutzererfahrung entscheidend.
Hauptmethoden: Entfernen ungenutzter Ressourcen und Codes (R8/ProGuard verwenden), Bilder vektorisieren (VectorDrawable, SF Symbols), PNG/WebP komprimieren (Android), App Bundle statt APK verwenden, unnötige Bibliotheken entfernen, Lazy Loading für Module verwenden. Größenoptimierung kann die APK um 40-60% reduzieren.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.