Nutzer erwarten, dass Apps schnell geladen werden und reagieren. Eine App mit einer langen Startzeit entspricht nicht dieser Erwartung und kann Nutzer enttäuschen. Ein solches schlechtes Nutzererlebnis kann dazu führen, dass Nutzer Ihre App im Play Store schlecht bewerten oder sie sogar 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 Zuständen interagieren.
Zwei wichtige Messwerte zur Bestimmung des App-Starts sind Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) und Zeit bis zum vollständigen Rendern (Time to Fully Drawn, 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 durch die TTID erfährt, dass die App geladen wird, und die 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 den 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.
- Aufrufe künstlich in die Höhe treiben
- Display gestalten
- Führen Sie die erste Ziehung durch.
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.
Abbildung 1 zeigt, wie die System- und App-Prozesse die Arbeit untereinander aufteilen.
Leistungsprobleme können bei der Erstellung der App und der Aktivitä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 Hauptaktivität beauftragt.
Ab diesem Punkt werden Prozesse auf System- und App-Ebene gemäß den Phasen des App-Lebenszyklus fortgesetzt.
Aktivität 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.
Normalerweise hat die Methode onCreate() den größten Einfluss auf die Ladezeit, da sie die Arbeit mit dem höchsten Overhead ausführt: Laden und Aufblähen von Ansichten sowie Initialisieren der Objekte, die für die Ausführung der Aktivität erforderlich sind.
Warm start
Ein Warmstart umfasst eine Teilmenge der Vorgänge, die während eines Kaltstarts stattfinden. Gleichzeitig ist der Aufwand höher als bei einem Heißstart. Es gibt viele potenzielle Status, die als Warmstarts infrage kommen, z. B. die folgenden:
Der Nutzer verlässt Ihre App, startet sie aber dann wieder. Der Prozess wird möglicherweise fortgesetzt, aber die App muss die Aktivität von Grund auf neu erstellen. Dazu muss sie
onCreate()aufrufen.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 Ihre Activity in den Vordergrund gerückt. Wenn sich alle Aktivitäten Ihrer App noch im Arbeitsspeicher befinden, kann die App die wiederholte Objektinitialisierung, das Layout-Inflating und das Rendern vermeiden.
Wenn jedoch aufgrund von Ereignissen zum Reduzieren 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 3. Die abgeleitete Metriksegmentierung „Android App Startups“ in Perfetto. Klicken Sie auf das zugehörige 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, d können Sie herauszoomen, nach links und nach rechts verschieben.
Abbildung 4. Der abgeleitete Messwert-Slice „Android App Startups“ neben dem Hauptthread der App. Der abgeleitete Messwert „Slice“ erleichtert es, genau zu sehen, was im App-Start enthalten ist, damit Sie weiterhin detaillierter debuggen können.
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 Startup-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.
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
- Aktivität erstellen und initialisieren
- Layout wird aufgeblasen.
- 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 3 s 534 ms 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-Menü für Filter und suchen Sie dann nach der Zeit Displayed, wie in Abbildung 5 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 Layoutdatei nicht verwiesen wird oder 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.
Manchmal enthält die Zeile Displayed in der Logcat-Ausgabe ein zusätzliches Feld für die Gesamtzeit. Beispiel:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
In diesem Fall erfolgt die erste Zeitmessung nur für die Aktivität, die zuerst gezeichnet wird. 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 den Startzeiten für die einzelne Aktivität und den Gesamtstartzeiten 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, um für den Nutzer interaktiv zu werden. Sie wird als die Zeit angegeben, 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: Die TTFD umfasst die 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 bestimmt die TTID, wenn Choreographer die Methode onDraw() der Aktivität aufruft und wenn es weiß, dass dies zum ersten Mal geschieht.
Das System weiß jedoch nicht, wann die TTFD bestimmt werden soll, da sich jede App anders verhält. 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 gezeichneten 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 das System den Intent zum Starten der App empfängt und reportFullyDrawn() aufgerufen wird. 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 vom System gezeichnet und angezeigt 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, zeigt Logcat eine Ausgabe wie im folgenden Beispiel an, 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 Ihr Benchmark-Timing einbeziehen.
Wenn die Benutzeroberfläche beispielsweise eine dynamische Liste wie eine RecyclerView- oder Lazy-Liste enthält, wird diese möglicherweise durch eine Hintergrundaufgabe gefüllt, die erst abgeschlossen wird, nachdem die Liste zum ersten Mal gezeichnet wurde und die Benutzeroberfläche daher als vollständig gezeichnet markiert wurde.
In solchen Fällen wird das Füllen der Liste nicht in die Benchmarking-Analyse einbezogen.
Wenn Sie das Ausfüllen der Liste in Ihre Benchmark-Zeit einbeziehen möchten, rufen Sie die FullyDrawnReporter mit getFullyDrawnReporter() 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, bis der Hintergrundprozess abgeschlossen ist, enthalten die Zeitangaben auch die Zeit, die zum Auffüllen der Liste in den Startzeitdaten benötigt wird. Das Verhalten der App für den Nutzer ändert sich dadurch nicht, aber die Timing-Startdaten umfassen die Zeit, die zum Füllen der Liste benötigt wird. reportFullyDrawn() wird erst aufgerufen, wenn alle Aufgaben abgeschlossen sind, unabhängig von der Reihenfolge.
Das folgende Beispiel zeigt, wie Sie mehrere Hintergrundaufgaben gleichzeitig ausführen können, wobei jede ihren eigenen Reporter registriert:
Kotlin
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()
}
}
}
}
}
Java
public class MainActivity extends ComponentActivity {
private FullyDrawnReporter fullyDrawnReporter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fullyDrawnReporter = getFullyDrawnReporter();
fullyDrawnReporter.addOnReportDrawnListener(() -> {
// Trigger the UI update.
return Unit.INSTANCE;
});
new Thread(new Runnable() {
@Override
public void run() {
fullyDrawnReporter.addReporter();
// Do the background work.
fullyDrawnReporter.removeReporter();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
fullyDrawnReporter.addReporter();
// Do the background work.
fullyDrawnReporter.removeReporter();
}
}).start();
}
}
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 das Composable sofort für die Interaktion bereit ist.ReportDrawnWhen: Akzeptiert ein Prädikat wielist.count > 0, um anzugeben, wann das 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.
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.
Außerdem können Sie 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 umfangreiche Aufgaben oder komplexe Logik ausgeführt werden. 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 Speicherbereinigungsereignisse, die sich stark auswirken oder zahlreich sind, oder die gleichzeitige Ausführung von Festplatten-E/A-Vorgängen, die den Initialisierungsprozess zusätzlich blockieren. 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, z. B.:
- 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-Initialisierung. 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:
- Aufblasen großer oder komplexer Layouts
- 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 Aktivität.
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-Profilers 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 das Inline-Tracing, um wahrscheinliche Ursachen zu untersuchen, z. B.:
- Die ursprüngliche
onCreate()-Funktion Ihrer App. - Alle globalen Singleton-Objekte, die 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
Es gibt viele potenzielle Engpässe, aber zwei häufige Probleme und Abhilfemaßnahmen sind:
- Je größer die Ansichtshierarchie ist, desto länger dauert es, bis die App sie aufbaut. Sie haben zwei Möglichkeiten, dieses Problem zu beheben:
- Sie können die Ansichtshierarchie vereinfachen, indem Sie redundante oder verschachtelte Layouts reduzieren.
- Blähen Sie keine Teile der Benutzeroberfläche auf, die beim Start nicht sichtbar sein müssen.
Verwenden Sie stattdessen ein
ViewStub-Objekt als Platzhalter für untergeordnete Hierarchien, die die App zu einem geeigneteren Zeitpunkt aufblähen kann.
- 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.
- Lassen Sie die App Ihre Ansichten laden und anzeigen und aktualisieren Sie später visuelle Eigenschaften, die von Bitmaps und anderen Ressourcen abhängen.
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
windowDisablePreviewdes Designs kö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:
- Sie können das Erscheinungsbild des Splash-Screens ändern, indem Sie ein Design festlegen.
- 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}