Nutzer erwarten, dass Apps schnell geladen werden und reagieren. Eine App mit einer langsamen Startzeit entspricht nicht dieser Erwartung und kann Nutzer enttäuschen. Ein schlechtes Nutzererlebnis kann dazu führen, dass Nutzer Ihre App im Play Store schlecht bewerten oder sie gar nicht mehr verwenden.
Auf dieser Seite finden Sie Informationen zur Optimierung der Startzeit Ihrer App, einschließlich einer Übersicht über die Interna des Startvorgangs, Informationen zum Profiling der Startleistung und einige häufige Probleme mit der Startzeit sowie Tipps zur Behebung dieser Probleme.
Die verschiedenen App-Startzustände
Der App-Start kann in einem von drei Zuständen erfolgen: Kaltstart, Warmstart oder Heißstart. Jeder Status wirkt sich darauf aus, wie lange es dauert, bis Ihre App für den Nutzer sichtbar wird. Bei einem Kaltstart wird Ihre App von Grund auf neu gestartet. In den anderen Bundesstaaten muss das System die laufende App vom Hintergrund in den Vordergrund holen.
Wir empfehlen, immer von einem Kaltstart auszugehen. Dadurch kann auch die Leistung von Warm- und Heißstarts verbessert werden.
Um Ihre App für einen schnellen Start zu optimieren, ist es hilfreich zu verstehen, was auf System- und App-Ebene passiert und wie sie in den einzelnen Status interagieren.
Zwei wichtige Messwerte zur Bestimmung des App-Starts sind Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) und Zeit bis zur vollständigen Anzeige (Time to Full Display, TTFD). TTID ist die Zeit, die zum Anzeigen des ersten Frames benötigt wird, und TTFD ist die Zeit, die benötigt wird, bis die App vollständig interaktiv ist. Beide sind gleichermaßen wichtig, da der Nutzer anhand von TTID sieht, dass die App geladen wird, und TTFD angibt, wann die App tatsächlich nutzbar ist. Wenn einer dieser Schritte zu lange dauert, verlässt der Nutzer Ihre App möglicherweise, bevor sie vollständig geladen ist.
Kaltstart
Ein Kaltstart bezieht sich auf den Neustart einer App. Das bedeutet, dass bis zu diesem Start der Prozess des Systems den Prozess der App erstellt. Kaltstarts treten beispielsweise auf, wenn Ihre App zum ersten Mal seit dem Start des Geräts oder seit dem Beenden der App durch das System gestartet wird.
Diese Art des Starts stellt die größte Herausforderung in Bezug auf die Minimierung der Startzeit dar, da das System und die App mehr leisten müssen als in anderen Startzuständen.
Zu Beginn eines Kaltstarts hat das System die folgenden drei Aufgaben:
- Laden Sie die App und starten Sie sie.
- Nach dem Start der App wird sofort ein leeres Startfenster angezeigt.
- Erstellen Sie den Prozess für die App.
Sobald das System den App-Prozess erstellt hat, ist dieser für die nächsten Phasen verantwortlich:
- Erstellen Sie das App-Objekt.
- Starten Sie den Hauptthread.
- Erstellen Sie die Hauptaktivität.
- Initialisieren Sie die Benutzeroberfläche.
- Zeichne die Benutzeroberfläche auf dem Display.
Wenn der App-Prozess den ersten Draw abgeschlossen hat, tauscht der Systemprozess das angezeigte Hintergrundfenster aus und ersetzt es durch die Hauptaktivität. An diesem Punkt kann der Nutzer die App verwenden.
Weitere Informationen zu Layoutphasen in Compose finden Sie unter Jetpack Compose-Phasen.
Leistungsprobleme können bei der Erstellung der App und der Hostaktivität auftreten.
App-Erstellung
Wenn Ihre App gestartet wird, bleibt das leere Startfenster auf dem Bildschirm, bis das System die App zum ersten Mal gezeichnet hat. An diesem Punkt tauscht der Systemprozess das Startfenster für Ihre App aus, sodass der Nutzer mit der App interagieren kann.
Wenn Sie Application.onCreate in Ihrer eigenen App überschreiben, ruft das System die Methode onCreate für Ihr App-Objekt auf. Anschließend wird der Hauptthread, auch UI-Thread genannt, gestartet und mit der Erstellung der Hostaktivität der App beauftragt.
Ab diesem Punkt werden Prozesse auf System- und App-Ebene gemäß den Phasen des App-Lebenszyklus fortgesetzt.
Aktivitäten erstellen
Nachdem der App-Prozess Ihre Aktivität erstellt hat, werden die folgenden Vorgänge ausgeführt:
- Initialisiert Werte.
- Ruft Konstruktoren auf.
- Ruft die Callback-Methode auf, z. B.
Activity.onCreate, die dem aktuellen Lebenszyklusstatus der Aktivität entspricht.
In der Regel hat die onCreate-Methode die größten Auswirkungen auf die Ladezeit. In einer Jetpack Compose-App entsteht der Overhead der onCreate-Methode oft durch die erste Komposition. Das passiert, wenn Ihre App setContent aufruft und Ihre Composables auf oberster Ebene aufgerufen werden. Eine tiefe oder komplexe UI-Hierarchie oder Composables, die rechenintensive Berechnungen im Hauptthread ausführen, können diese Kompositionszeit verlängern.
Warm start
Ein Warmstart umfasst eine Teilmenge der Vorgänge, die bei einem Kaltstart stattfinden. Gleichzeitig ist der Aufwand höher als bei einem Heißstart. Es gibt viele potenzielle Status, die als Warmstarts betrachtet werden können, z. B. die folgenden:
Der Nutzer verlässt Ihre App, startet sie aber dann neu. Der Prozess wird möglicherweise fortgesetzt, aber die App muss die Aktivität von Grund auf neu erstellen. Dazu muss sie
onCreateaufrufen.Das System entfernt Ihre App aus dem Arbeitsspeicher und der Nutzer startet sie dann neu. Der Prozess und die Aktivität müssen neu gestartet werden, aber die Aufgabe kann etwas von dem gespeicherten Instanzstatus-Bundle profitieren, das an
onCreateübergeben wird.
Heißstart
Ein Heißstart Ihrer App hat einen geringeren Aufwand als ein Kaltstart. Bei einem Heißstart wird die Hostaktivität Ihrer App in den Vordergrund gebracht. Wenn die gesamte Benutzeroberfläche Ihrer App noch im Arbeitsspeicher vorhanden ist, kann die App die wiederholte Initialisierung von Objekten, die Initialisierung der Benutzeroberfläche und das Rendern vermeiden.
Wenn jedoch aufgrund von Ereignissen zum Kürzen des Arbeitsspeichers, z. B. onTrimMemory, Arbeitsspeicher freigegeben wird, müssen diese Objekte als Reaktion auf das Heißstart-Ereignis neu erstellt werden.
Bei einem Hot-Start wird auf dem Bildschirm dasselbe Verhalten wie bei einem Kaltstart angezeigt. Der Systemprozess zeigt einen leeren Bildschirm an, bis die App die Aktivität gerendert hat.
App-Start in Perfetto identifizieren
Um Probleme beim Starten der App zu beheben, ist es hilfreich, genau zu wissen, was in der Startphase der App passiert. So identifizieren Sie die gesamte App-Startphase in Perfetto:
Suchen Sie in Perfetto nach der Zeile mit dem abgeleiteten Messwert „Android App Startups“. Wenn Sie sie nicht sehen, versuchen Sie, einen Trace mit der App für die Systemanalyse auf dem Gerät aufzuzeichnen.
Abbildung 2. Der abgeleitete Messwert-Slice „Android App Startups“ in Perfetto. Klicken Sie auf das entsprechende Segment und drücken Sie m, um es auszuwählen. Klammern um den Abschnitt geben an, wie lange er gedauert hat. Die Dauer wird auch auf dem Tab Aktuelle Auswahl angezeigt.
Pinnen Sie die Zeile „Android App Startups“, indem Sie auf das Pinsymbol klicken, das angezeigt wird, wenn Sie den Mauszeiger auf die Zeile bewegen.
Scrollen Sie zur Zeile mit der betreffenden App und klicken Sie auf die erste Zelle, um die Zeile zu maximieren.
Zoomen Sie in den Hauptthread, der sich normalerweise oben befindet, indem Sie w drücken. Mit s, a und d können Sie herauszoomen, nach links und nach rechts verschieben.
Abbildung 3. Der abgeleitete Messwert-Slice „Android App Startups“ neben dem Hauptthread der App. Mit dem abgeleiteten Messwertsegment lässt sich leichter nachvollziehen, was genau beim App-Start enthalten ist. So können Sie weiterhin detaillierter debuggen.
Wenn Sie eine Jetpack Compose-Anwendung analysieren, können Sie Composition Tracing verwenden, um detaillierte Informationen zur Leistung Ihrer Benutzeroberfläche zu erhalten.
Achten Sie besonders auf Trace-Abschnitte im Hauptthread, die mit Choreographer#doFrame beginnen. Suchen Sie nach Segmenten wie Compose:recompose, Compose:layout und Compose:draw. Sie zeigen, wie viel Zeit Ihre App für das Erstellen, Messen, Platzieren und Zeichnen bestimmter Komponenten benötigt.
Messwerte verwenden, um Start-ups zu analysieren und zu verbessern
Um die Leistung der Startzeit richtig zu analysieren, können Sie Messwerte erfassen, die zeigen, wie lange es dauert, bis Ihre App gestartet wird. Android bietet verschiedene Möglichkeiten, um Sie darauf hinzuweisen, dass Ihre App ein Problem hat, und Ihnen bei der Diagnose zu helfen. Android Vitals kann Sie benachrichtigen, wenn ein Problem auftritt, und Diagnosetools können Ihnen helfen, das Problem zu diagnostizieren.
Vorteile der Verwendung von Start-up-Messwerten
Android verwendet die Messwerte Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) und Zeit bis zur vollständigen Anzeige (Time to Full Display, TTFD), um Kalt- und Warmstarts von Apps zu optimieren. Die Android-Laufzeit (Android Runtime, ART) verwendet die Daten aus diesen Messwerten, um Code effizient vorzukompilieren und so zukünftige Starts zu optimieren.
Schnellere Starts führen zu einer längeren Nutzerinteraktion mit Ihrer App. Dadurch wird die Wahrscheinlichkeit verringert, dass Nutzer die App frühzeitig beenden, die Instanz neu starten oder zu einer anderen App wechseln.
Android Vitals
Android Vitals kann Ihnen helfen, die Leistung Ihrer App zu verbessern, indem Sie in der Play Console benachrichtigt werden, wenn die Startzeiten Ihrer App zu lang sind.
In Android Vitals gelten die folgenden Startzeiten für Ihre App als zu lang:
- Der Kaltstart dauert 5 Sekunden oder länger.
- Der Warmstart dauert 2 Sekunden oder länger.
- Der Heißstart dauert mindestens 1,5 Sekunden.
Für Android Vitals wird der Messwert Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) verwendet. Informationen dazu, wie Google Play Android Vitals-Daten erhebt, finden Sie in der Play Console-Dokumentation.
Zeit bis zur ersten Anzeige
Die Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) ist die Zeit, die benötigt wird, um den ersten Frame der Benutzeroberfläche der App anzuzeigen. Mit diesem Messwert wird die Zeit gemessen, die eine App benötigt, um den ersten Frame zu rendern. Dazu gehören die Prozessinitialisierung bei einem Kaltstart, die Aktivitätserstellung bei einem Kalt- oder Warmstart und die Anzeige des ersten Frames. Wenn die TTID Ihrer App niedrig ist, wird die Nutzerfreundlichkeit verbessert, da Nutzer sehen, dass Ihre App schnell gestartet wird. Die TTID wird für jede App automatisch vom Android-Framework gemeldet. Wenn Sie die App-Startzeit optimieren möchten, empfehlen wir die Implementierung von reportFullyDrawn, um Informationen bis zum TTFD zu erhalten.
Die TTID wird als Zeitwert gemessen, der die gesamte verstrichene Zeit umfasst, die für die folgende Ereignissequenz benötigt wird:
- Den Prozess starten
- Objekte initialisieren
- Erstellen und Initialisieren der Hostaktivität
- Benutzeroberfläche wird initialisiert.
- Die App wird zum ersten Mal gezeichnet.
TTID abrufen
Suchen Sie im Logcat-Befehlszeilentool nach einer Ausgaberzeile mit dem Wert Displayed, um die TTID zu finden. Dieser Wert ist die TTID und sieht in etwa so aus wie im folgenden Beispiel, in dem die TTID 3s534ms beträgt:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
Wenn Sie die TTID in Android Studio finden möchten, deaktivieren Sie die Filter in der Logcat-Ansicht über das Drop-down-Filtermenü und suchen Sie dann nach der Displayed-Zeit, wie in Abbildung 4 dargestellt.
Das Deaktivieren der Filter ist erforderlich, da dieser Log vom Systemserver und nicht von der App selbst bereitgestellt wird.
Displayed in LogcatDer Messwert Displayed in der Logcat-Ausgabe erfasst nicht unbedingt die Zeit, bis alle Ressourcen geladen und angezeigt werden. Es werden Ressourcen ausgelassen, auf die in der ursprünglichen Komposition nicht verwiesen wird (z. B. asynchron geladene Daten oder Bilder) oder Ressourcen, die von der App im Rahmen der Objektinitialisierung erstellt werden. Diese Ressourcen werden ausgeschlossen, weil das Laden ein Inline-Prozess ist und die anfängliche Darstellung der App nicht blockiert.
Weitere Informationen zu Ressourcen finden Sie unter Ressourcen in Compose.
Manchmal enthält die Displayed-Zeile in der Logcat-Ausgabe ein zusätzliches Feld für die Gesamtzeit, wie im folgenden Beispiel:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
In diesem Fall wird die erste Zeitmessung nur für die Aktivität durchgeführt, die zuerst gezeichnet wird, in der Regel die Host-Aktivität. Die Zeitmessung für total beginnt mit dem Start des App-Prozesses und kann eine andere Aktivität umfassen, die zuerst gestartet wird, aber nichts auf dem Bildschirm anzeigt. Die Zeitmessung total wird nur angezeigt, wenn es einen Unterschied zwischen der einzelnen Aktivität und der gesamten Startzeit gibt.
Wir empfehlen, Logcat in Android Studio zu verwenden. Wenn Sie Android Studio nicht verwenden, können Sie die TTID auch messen, indem Sie Ihre App mit dem adb-Shell-Befehl des Activity Managers ausführen. Beispiel:
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN
Der Messwert Displayed wird wie bisher in der Logcat-Ausgabe angezeigt. In Ihrem Terminalfenster wird Folgendes angezeigt:
Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete
Die Argumente -c und -a sind optional und ermöglichen es Ihnen, <category> und <action> anzugeben.
Zeit bis zur vollständigen Anzeige
Die Zeit bis zur vollständigen Anzeige (Time to Full Display, TTFD) ist die Zeit, die eine App benötigt, bis sie für den Nutzer interaktiv wird. Sie gibt die Zeit an, die benötigt wird, um den ersten Frame der Benutzeroberfläche der App sowie die Inhalte anzuzeigen, die asynchron geladen werden, nachdem der erste Frame angezeigt wurde. In der Regel handelt es sich dabei um primäre Inhalte, die aus dem Netzwerk oder von der Festplatte geladen werden, wie von der App gemeldet. Mit anderen Worten: TTFD umfasst TTID sowie die Zeit, die benötigt wird, bis die App verwendet werden kann. Wenn die TTFD Ihrer App niedrig ist, können Nutzer schnell mit Ihrer App interagieren, was die Nutzerfreundlichkeit verbessert.
Das System kann zwar die TTID bestimmen, wenn das Hostfenster seinen ersten Frame rendert, aber die TTFD kann nicht automatisch bestimmt werden. Da Apps ihre primären Inhalte oft asynchron laden, weiß das System nicht, wann die App für den Nutzer tatsächlich vollständig nutzbar ist. Um die TTFD zu ermitteln, muss die App dem System signalisieren, wenn sie den vollständig gerenderten Zustand erreicht.
TTFD abrufen
Um TTFD zu ermitteln, signalisieren Sie den vollständig gerenderten Zustand, indem Sie die Methode reportFullyDrawn des ComponentActivity aufrufen. Die Methode reportFullyDrawn gibt an, wann die App vollständig gerendert wurde und sich in einem nutzbaren Zustand befindet. Die TTFD ist die Zeit, die vergeht, bis reportFullyDrawn aufgerufen wird, nachdem das System den Intent zum Starten der App empfangen hat. Wenn Sie reportFullyDrawn nicht aufrufen, wird kein TTFD-Wert gemeldet.
Rufen Sie reportFullyDrawn auf, nachdem Sie die Benutzeroberfläche und alle Daten vollständig gerendert haben, um die TTFD zu messen. Rufen Sie reportFullyDrawn nicht auf, bevor das Fenster der ersten Aktivität zum ersten Mal gezeichnet und vom System gemessen wird, da das System sonst die vom System gemessene Zeit meldet. Wenn Sie reportFullyDrawn aufrufen, bevor das System die TTID erkennt, werden sowohl TTID als auch TTFD als derselbe Wert gemeldet. Dieser Wert ist der TTID-Wert.
Wenn Sie reportFullyDrawn verwenden, wird in Logcat eine Ausgabe wie im folgenden Beispiel angezeigt, in dem die TTFD 1 s 54 ms beträgt:
system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
Die Logcat-Ausgabe enthält manchmal eine total-Zeit, wie unter Zeit bis zur ersten Anzeige beschrieben.
Wenn die Anzeigezeiten langsamer sind als gewünscht, können Sie versuchen, die Engpässe im Startvorgang zu ermitteln.
Mit reportFullyDrawn können Sie den vollständig gezeichneten Zustand in einfachen Fällen signalisieren, in denen Sie wissen, dass er erreicht wird. Wenn Hintergrundthreads jedoch Hintergrundaufgaben ausführen müssen, bevor der vollständig gerenderte Zustand erreicht wird, müssen Sie reportFullyDrawn verzögern, um eine genauere TTFD-Messung zu erhalten. Informationen dazu, wie Sie reportFullyDrawn verzögern, finden Sie im folgenden Abschnitt.
Genauigkeit der Startzeit verbessern
Wenn Ihre App Lazy Loading verwendet und die erste Anzeige nicht alle Ressourcen enthält, z. B. wenn Ihre App Bilder aus dem Netzwerk abruft, sollten Sie den Aufruf von reportFullyDrawn möglicherweise verzögern, bis Ihre App nutzbar ist. So können Sie die Listenerstellung in Ihre Benchmark-Zeitmessung einbeziehen.
Wenn die Benutzeroberfläche beispielsweise eine dynamische Liste wie LazyColumn oder LazyRow enthält, wird diese möglicherweise durch eine Hintergrundaufgabe gefüllt, die erst abgeschlossen wird, nachdem die Liste zum ersten Mal gerendert wurde und die Benutzeroberfläche daher als vollständig gerendert markiert ist. In solchen Fällen wird das Füllen der Liste nicht in die Benchmarking-Analyse einbezogen.
Wenn Sie das Ausfüllen der Liste in Ihr Benchmark-Timing einbeziehen möchten, rufen Sie die FullyDrawnReporter mit fullyDrawnReporter ab und fügen Sie ihr in Ihrem App-Code einen Reporter hinzu. Geben Sie den Reporter frei, nachdem die Liste durch den Hintergrundtask gefüllt wurde.
FullyDrawnReporter ruft die Methode reportFullyDrawn erst auf, wenn alle hinzugefügten Reporter freigegeben wurden. Wenn Sie einen Reporter hinzufügen, ihn aber erst freigeben, wenn der Hintergrundprozess abgeschlossen ist, sind die Startzeitdaten auch die Zeit, die zum Erstellen der Liste benötigt wird. Das Verhalten der App für den Nutzer ändert sich dadurch nicht. reportFullyDrawn wird erst aufgerufen, wenn alle Aufgaben abgeschlossen sind, unabhängig von der Reihenfolge.
Wenn Ihre App Jetpack Compose verwendet, können Sie mit den folgenden APIs angeben, dass die App vollständig gerendert wurde:
ReportDrawn: Gibt an, dass Ihr Composable sofort für die Interaktion bereit ist.ReportDrawnWhen: Akzeptiert ein Prädikat wielist.count > 0, um anzugeben, wann Ihre Composable für die Interaktion bereit ist.ReportDrawnAfter: Nimmt eine Methode zum Anhalten entgegen, die nach Abschluss angibt, dass das Composable für die Interaktion bereit ist.
Das folgende Beispiel zeigt, wie Sie mehrere Hintergrundaufgaben gleichzeitig ausführen können, wobei jede ihren eigenen Reporter registriert:
class MainActivity : ComponentActivity() {
sealed interface ActivityState {
data object LOADING : ActivityState
data object LOADED : ActivityState
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var activityState by remember {
mutableStateOf(ActivityState.LOADING as ActivityState)
}
fullyDrawnReporter.addOnReportDrawnListener {
activityState = ActivityState.LOADED
}
ReportFullyDrawnTheme {
when(activityState) {
is ActivityState.LOADING -> {
// Display the loading UI.
}
is ActivityState.LOADED -> {
// Display the full UI.
}
}
}
SideEffect {
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
}
}
}
}
Engpässe identifizieren
Mit dem CPU Profiler von Android Studio können Sie nach Engpässen suchen. Weitere Informationen finden Sie unter CPU-Aktivität mit CPU Profiler untersuchen.
Sie können auch durch Inline-Tracing in den onCreate-Methoden Ihrer Apps und Aktivitäten potenzielle Engpässe erkennen. Informationen zum Inline-Tracing finden Sie in der Dokumentation zu den Trace-Funktionen und in der Übersicht zum System-Tracing.
Häufige Probleme beheben
In diesem Abschnitt werden verschiedene Probleme behandelt, die sich häufig auf die Startleistung von Apps auswirken. Diese Probleme betreffen hauptsächlich die Initialisierung von App- und Aktivitätsobjekten sowie das Laden von Bildschirmen.
Aufwendige App-Initialisierung
Die Startleistung kann beeinträchtigt werden, wenn Ihr Code das Application-Objekt überschreibt und beim Initialisieren dieses Objekts rechenintensive oder komplexe Logik ausgeführt wird. Ihre App verschwendet möglicherweise Zeit beim Start, wenn Ihre Application-Unterklassen Initialisierungen ausführen, die noch nicht erforderlich sind.
Einige Initialisierungen sind möglicherweise völlig unnötig, z. B. wenn Statusinformationen für die Hauptaktivität initialisiert werden, wenn die App tatsächlich als Reaktion auf einen Intent gestartet wird. Bei einem Intent verwendet die App nur eine Teilmenge der zuvor initialisierten Statusdaten.
Weitere Herausforderungen bei der Initialisierung von Apps sind automatische Speicherbereinigung-Ereignisse, die sich stark auswirken oder zahlreich sind, oder Festplatten-E/A, die gleichzeitig mit der Initialisierung erfolgt und den Initialisierungsprozess weiter blockiert. Die automatische Speicherbereinigung ist besonders bei der Dalvik-Laufzeit ein wichtiger Faktor. Die Android-Laufzeit (ART) führt die automatische Speicherbereinigung gleichzeitig aus, wodurch die Auswirkungen dieses Vorgangs minimiert werden.
Problem diagnostizieren
Sie können versuchen, das Problem mit der Methodenverfolgung oder der Inline-Verfolgung zu diagnostizieren.
Methoden-Tracing
Wenn Sie den CPU-Profiler ausführen, sehen Sie, dass die Methode callApplicationOnCreate schließlich Ihre com.example.customApplication.onCreate-Methode aufruft. Wenn das Tool anzeigt, dass die Ausführung dieser Methoden lange dauert, sollten Sie genauer untersuchen, welche Vorgänge dort ausgeführt werden.
Inline-Tracing
Verwenden Sie Inline-Tracing, um wahrscheinliche Ursachen zu untersuchen, darunter:
- Die ursprüngliche
onCreate-Funktion Ihrer App. - Alle globalen Singleton-Objekte, die von Ihrer App initialisiert werden.
- Alle Festplatten-E/A-Vorgänge, Deserialisierungen oder engen Schleifen, die während des Engpasses auftreten können.
Lösungen für das Problem
Unabhängig davon, ob das Problem bei unnötigen Initialisierungen oder bei der Festplatten-E/A liegt, ist die Lösung die Lazy Initialization. Initialisieren Sie also nur Objekte, die sofort benötigt werden. Anstatt globale statische Objekte zu erstellen, sollten Sie ein Singleton-Muster verwenden, bei dem die App Objekte nur beim ersten Mal initialisiert, wenn sie sie benötigt.
Sie können auch ein Framework für die Abhängigkeitsinjektion wie Hilt verwenden, das Objekte und Abhängigkeiten erstellt, wenn sie zum ersten Mal eingefügt werden.
Wenn Ihre App Contentanbieter verwendet, um App-Komponenten beim Start zu initialisieren, sollten Sie stattdessen die App Startup-Bibliothek verwenden.
Initialisierung bei intensiver Aktivität
Das Erstellen von Aktivitäten ist oft mit viel Aufwand verbunden. Häufig gibt es Möglichkeiten, diese Arbeit zu optimieren, um die Leistung zu verbessern. Häufige Probleme sind:
- Initialisieren einer großen oder komplexen Benutzeroberfläche
- Umfangreiche Initialisierung in Composables
- Das Zeichnen des Bildschirms auf der Festplatte oder die Netzwerk-E/A wird blockiert.
- Bitmaps laden und decodieren.
VectorDrawable-Objekte werden gerastert.- Initialisierung anderer Subsysteme der Hostaktivität der App.
Problem diagnostizieren
Auch in diesem Fall können sowohl die Methoden- als auch die Inline-Ablaufverfolgung nützlich sein.
Methoden-Tracing
Achten Sie bei der Verwendung des CPU Profiler auf die Konstruktoren der Application-Unterklasse und die com.example.customApplication.onCreate-Methoden Ihrer App.
Wenn das Tool anzeigt, dass die Ausführung dieser Methoden lange dauert, sollten Sie genauer untersuchen, was dort passiert.
Inline-Tracing
Verwenden Sie Inline-Tracing, um wahrscheinliche Ursachen zu untersuchen, darunter:
- Die ursprüngliche
onCreate-Funktion Ihrer App. - Alle globalen Singleton-Objekte, die initialisiert werden.
- Alle Datenträger-E/A-Vorgänge, Deserialisierungen oder engen Schleifen, die während des Engpasses auftreten können.
Lösungen für das Problem
Es gibt viele potenzielle Engpässe, aber zwei häufige Probleme und Abhilfemaßnahmen sind:
- Je größer die UI-Hierarchie, desto länger dauert es, bis die App sie initialisiert.
Gehen Sie so vor, um das Problem zu beheben:
- Flachen Sie die UI-Hierarchie ab, indem Sie redundante oder verschachtelte Composables reduzieren.
- Vermeiden Sie unnötige Kompositionen und Neukompositionen beim Start.
- Zusammensetzung der nicht kritischen Benutzeroberfläche verzögern
- Wenn die gesamte Ressourceninitialisierung im Hauptthread erfolgt, kann sich auch der Start verlangsamen. So können Sie das Problem beheben:
- Verschieben Sie die gesamte Ressourceninitialisierung, damit die App sie verzögert in einem anderen Thread ausführen kann.
- Laden und rendern Sie die Benutzeroberfläche zuerst mit Platzhalterdaten und aktualisieren Sie dann visuelle Eigenschaften, die von Bitmaps und anderen Ressourcen abhängig sind.
Weitere Informationen zur Neukomposition finden Sie unter Neukomposition und Anzahl der Neukompositionen abrufen.
Benutzerdefinierte Ladebildschirme
Wenn Sie zuvor eine der folgenden Methoden verwendet haben, um unter Android 11 (API-Level 30) oder niedriger einen benutzerdefinierten Ladebildschirm zu implementieren, kann es beim Starten der App zu einer zusätzlichen Verzögerung kommen:
- Mit dem Attribut
windowDisablePreviewkönnen Sie den anfänglichen leeren Bildschirm deaktivieren, der vom System beim Starten gezeichnet wird. - Verwenden Sie ein dediziertes
Activity.
Ab Android 12 ist die Migration zur SplashScreen API erforderlich.
Diese API ermöglicht eine schnellere Startzeit und bietet Ihnen die folgenden Möglichkeiten, den Splash-Screen anzupassen:
- Legen Sie ein Design fest, um die Darstellung des Startbildschirms zu ändern.
- Mit
windowSplashScreenAnimationDurationkönnen Sie festlegen, wie lange der Splash-Screen angezeigt wird. - Passen Sie die Ladebildschirmanimation an und sorgen Sie für eine reibungslose Animation beim Schließen des Ladebildschirms.
Außerdem wird die SplashScreen API durch die Compat-Bibliothek rückportiert, um Abwärtskompatibilität zu ermöglichen und ein einheitliches Erscheinungsbild für die Anzeige von Splash-Screens auf allen Android-Versionen zu schaffen.
Weitere Informationen finden Sie im Migrationsleitfaden für den Splash-Screen.
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Langsames Rendering
- Makrobenchmark-Messwerte erfassen
- Baseline-Profile erstellen{:#creating-profile-rules}