Ladezeit und Bildschirmdarstellung mit Firebase Performance Monitoring messen

1. Einführung

Letzte Aktualisierung: 11. März 2021

Warum müssen wir die Leistung von Aufrufen messen?

Ansichten sind ein wichtiger Bestandteil von Android-Anwendungen, der sich direkt auf die Nutzerfreundlichkeit auswirkt. Ihre Aktivität oder Ihr Fragment enthält beispielsweise die UI, die die View-Komponenten enthält, mit denen Nutzer interagieren. Nutzer können den gesamten Inhalt der Benutzeroberfläche erst sehen, wenn er vollständig auf dem Bildschirm dargestellt wird. Langsame und eingefrorene Bildschirme beeinträchtigen die Nutzerinteraktion mit Ihrer App direkt und führen zu einer schlechten Nutzererfahrung.

Werden diese Leistungsmesswerte nicht standardmäßig von Firebase Performance Monitoring bereitgestellt?

Firebase Performance Monitoring erfasst automatisch einige Leistungsdaten, z.B. die Startzeit Ihrer App (d.h. die Ladezeit nur für Ihre erste Aktivität) und die Bildschirm-Rendering-Leistung (langsame und eingefrorene Frames für Aktivitäten, aber nicht für Fragmente). Branchen-Apps haben jedoch in der Regel nicht viele Aktivitäten, sondern eine Aktivität und mehrere Fragmente. Außerdem implementieren viele Apps in der Regel eigene benutzerdefinierte Ansichten für komplexere Anwendungsfälle. Daher ist es oft hilfreich zu wissen, wie Sie die Ladezeit und die Bildschirmdarstellungsleistung sowohl von Aktivitäten als auch von Fragmenten messen können, indem Sie benutzerdefinierte Code-Traces in Ihrer App instrumentieren. Sie können dieses Codelab ganz einfach erweitern, um die Leistung von Komponenten für benutzerdefinierte Ansichten zu messen.

Aufgaben in diesem Lab

  • So fügen Sie einer Android-App Firebase Performance Monitoring hinzu
  • Informationen zum Laden einer Aktivität oder eines Fragments
  • Anleitung zum Instrumentieren benutzerdefinierter Code-Traces, um die Ladezeit einer Aktivität oder eines Fragments zu messen
  • Bildschirmrendering und langsame/eingefrorene Frames
  • Benutzerdefinierte Code-Traces mit Messwerten instrumentieren, um langsame/eingefrorene Bildschirme aufzuzeichnen
  • Erfasste Messwerte in der Firebase Console aufrufen

Voraussetzungen

  • Android Studio 4.0 oder höher
  • Ein Android-Gerät/-Emulator
  • Java-Version 8 oder höher

2. Einrichtung

Code abrufen

Führen Sie die folgenden Befehle aus, um den Beispielcode für dieses Codelab zu klonen. Dadurch wird auf Ihrem Computer ein Ordner mit dem Namen codelab-measure-android-view-performance erstellt:

$ git clone https://github.com/FirebaseExtended/codelab-measure-android-view-performance.git
$ cd codelab-measure-android-view-performance

Wenn auf Ihrem Computer kein Git vorhanden ist, können Sie den Code auch direkt von GitHub herunterladen.

Importieren Sie das Projekt measure-view-performance-start in Android Studio. Wahrscheinlich werden einige Kompilierungsfehler oder eine Warnung zu einer fehlenden google-services.json-Datei angezeigt. Das korrigieren wir im nächsten Abschnitt dieses Schritts.

In diesem Codelab verwenden wir das Plug-in Firebase Assistant, um unsere Android-App bei einem Firebase-Projekt zu registrieren und die erforderlichen Firebase-Konfigurationsdateien, Plug-ins und Abhängigkeiten zu unserem Android-Projekt hinzuzufügen – direkt in Android Studio.

App mit Firebase verbinden

  1. Prüfen Sie unter Android Studio/Hilfe > Nach Updates suchen, ob Sie die neuesten Versionen von Android Studio und Firebase Assistant verwenden.
  2. Wählen Sie Tools > Firebase aus, um den Bereich Assistant zu öffnen.

e791bed0999db1e0.png

  1. Wählen Sie Leistungsüberwachung aus, um sie Ihrer App hinzuzufügen, und klicken Sie dann auf Einführung in die Leistungsüberwachung.
  2. Klicken Sie auf Connect to Firebase (Mit Firebase verbinden), um Ihr Android-Projekt mit Firebase zu verbinden. Die Firebase Console wird in Ihrem Browser geöffnet.
  3. Klicken Sie in der Firebase Console auf Projekt hinzufügen und geben Sie einen Firebase-Projektnamen ein. Wenn Sie bereits ein Firebase-Projekt haben, können Sie stattdessen dieses vorhandene Projekt auswählen. Klicken Sie auf Weiter und akzeptieren Sie die Nutzungsbedingungen, um das Firebase-Projekt und eine neue Firebase-App zu erstellen.
  4. Als Nächstes sollte ein Dialogfeld angezeigt werden, in dem Sie Ihre neue Firebase App mit Ihrem Android Studio-Projekt verknüpfen können.

42c498d28ead2b77.png

  1. In Android Studio sollten Sie im Bereich Assistant die Bestätigung sehen, dass Ihre App mit Firebase verbunden ist.

dda8bdd9488167a0.png

App Performance Monitoring hinzufügen

Klicken Sie in Android Studio im Bereich Assistant auf App die Leistungsüberwachung hinzufügen.

Es sollte ein Dialogfeld mit der Aufforderung Änderungen akzeptieren angezeigt werden. Anschließend sollte Android Studio Ihre App synchronisieren, um sicherzustellen, dass alle erforderlichen Abhängigkeiten hinzugefügt wurden.

9b58145acc4be030.png

Schließlich sollte im Bereich Assistant in Android Studio die Erfolgsmeldung angezeigt werden, dass alle Abhängigkeiten korrekt eingerichtet sind.

aa0d46fc944e0c0b.png

Aktivieren Sie als zusätzlichen Schritt das Debug-Logging. Folgen Sie dazu der Anleitung unter „Optional: Debug-Logging aktivieren“. Die gleiche Anleitung finden Sie auch in der öffentlichen Dokumentation.

3. Anwendung ausführen

Wenn Sie Ihre App erfolgreich in das Performance Monitoring SDK eingebunden haben, sollte das Projekt jetzt kompiliert werden. Klicken Sie in Android Studio auf Ausführen > „App“ ausführen, um die App auf Ihrem verbundenen Android-Gerät/Emulator zu erstellen und auszuführen.

Die App verfügt über zwei Schaltflächen, über die Sie zu einer entsprechenden Aktivität und einem Fragment gelangen:

410d8686b4f45c33.png

In den folgenden Schritten dieses Codelabs erfahren Sie, wie Sie die Ladezeit und die Bildschirmdarstellungsleistung Ihrer Aktivität oder Ihres Fragments messen.

4. Informationen zum Laden einer Aktivität oder eines Fragments

In diesem Schritt erfahren wir, was das System beim Laden einer Aktivität oder eines Fragments tut.

Laden einer Aktivität

Bei einer Aktivität ist die Ladezeit als der Zeitraum ab der Erstellung des Activity-Objekts bis zur vollständigen Darstellung des ersten Frame auf dem Bildschirm definiert. Hierdurch sehen die Nutzer zum ersten Mal die vollständige Benutzeroberfläche für die Aktivität. Mit der Methode reportFullyDrawn() können Sie messen, ob Ihre App vollständig dargestellt wird. Dazu wird die verstrichene Zeit zwischen dem Start der App und der vollständigen Anzeige aller Ressourcen und Ansichtshierarchien gemessen.

Wenn Ihre App startActivity(Intent) aufruft, führt das System grob gesagt die folgenden Prozesse automatisch aus. Jeder Prozess nimmt einige Zeit in Anspruch, was die Zeitspanne zwischen der Erstellung der Aktivität und dem Zeitpunkt, zu dem der Benutzer die Benutzeroberfläche für die Aktivität auf seinem Bildschirm sieht, verlängert.

c20d14b151549937.png

Das Laden eines Fragments verstehen

Ähnlich wie bei der Aktivität wird die Ladezeit für ein Fragment als die Zeit definiert, die vergeht, bis das Fragment an seine Host-Aktivität angehängt ist und der erste Frame für die Fragmentansicht vollständig auf dem Bildschirm gezeichnet ist.

5. Ladezeit einer Aktivität messen

Verzögerungen beim ersten Frame können zu einer schlechten Nutzererfahrung führen. Daher ist es wichtig, zu wissen, wie lange die anfängliche Ladezeit für Ihre Nutzer ist. Sie können einen benutzerdefinierten Code-Trace instrumentieren, um diese Ladezeit zu messen:

  1. Starten Sie den benutzerdefinierten Code-Trace (benannt TestActivity-LoadTime) in der Aktivitätsklasse, sobald das Aktivitätsobjekt erstellt wurde.

TestActivity.java

public class TestActivity extends AppCompatActivity {   
    // TODO (1): Start trace recording as soon as the Activity object is created.
    private final Trace viewLoadTrace = FirebasePerformance.startTrace("TestActivity-LoadTime");

    // ...

}
  1. Überschreiben Sie den onCreate()-Callback und rufen Sie die Ansicht ab, die mit der setContentView()-Methode hinzugefügt wurde.
@Override     
public void onCreate(Bundle savedInstanceState) {    
    super.onCreate(savedInstanceState);          

    // Current Activity's main View (as defined in the layout xml file) is inflated after this            
    setContentView(R.layout.activity_test);          

    // ...

    // TODO (2): Get the View added by Activity's setContentView() method.         
    View mainView = findViewById(android.R.id.content);     

    // ...
}
  1. Wir haben eine Implementierung von FistDrawListener mit zwei Callbacks implementiert: onDrawingStart() und onDrawingFinish() (weitere Informationen zu FirstDrawListener und zu Faktoren, die die Leistung beeinflussen können, findest du im nächsten Abschnitt). Registrieren Sie die FirstDrawListener am Ende des onCreate()-Callbacks der Aktivität. Du solltest viewLoadTrace im onDrawingFinish()-Callback beenden.

TestActivity.java

    // TODO (3): Register the callback to listen for first frame rendering (see
    //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when View drawing is
    //  finished.
    FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {              
        @Override             
        public void onDrawingStart() {       
          // In practice you can also record this event separately
        }

        @Override             
        public void onDrawingFinish() {
            // This is when the Activity UI is completely drawn on the screen
            viewLoadTrace.stop();             
        }         
    });
  1. Führen Sie die App noch einmal aus. Filtern Sie dann den Logcat nach Logging trace metric. Tippen Sie auf die Schaltfläche LOAD ACTIVITY und suchen Sie nach Logs wie diesen:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Glückwunsch! Sie haben die Ladezeit einer Aktivität gemessen und die entsprechenden Daten an Firebase Performance Monitoring gesendet. Wir sehen uns den aufgezeichneten Messwert später in diesem Codelab in der Firebase Console an.

Zweck von FirstDrawListener

Im obigen Abschnitt haben wir ein FirstDrawListener registriert. Mit FirstDrawListener wird gemessen, wann das Zeichnen des ersten Frames begonnen und beendet wurde.

Es implementiert ViewTreeObserver.OnDrawListener und überschreibt den onDraw()-Callback, der aufgerufen wird, wenn der Ansichtsbaum gezeichnet werden soll. Das Ergebnis wird dann in zwei Dienst-Callbacks onDrawingStart() und onDrawingFinish() verpackt.

Den vollständigen Code für FirstDrawListener finden Sie im Quellcode dieses Codelab.

6. Ladezeit eines Fragments messen

Das Messen der Ladezeit eines Fragments ähnelt der Messung einer Aktivität, mit einigen geringfügigen Unterschieden. Wir instrumentieren wieder eine benutzerdefinierte Code-Spur:

  1. Überschreiben Sie den onAttach()-Callback und beginnen Sie mit der Aufzeichnung Ihrer fragmentLoadTrace. Wir nennen diesen Trace Test-Fragment-LoadTime.

Wie in einem früheren Schritt erläutert, kann das Fragmentobjekt jederzeit erstellt werden, es wird jedoch erst aktiv, wenn es an die zugehörige Aktivität angehängt wird.

TestFragment.java

public class TestFragment extends Fragment {

   // TODO (1): Declare the Trace variable.
   private Trace fragmentLoadTrace;

   @Override
   public void onAttach(@NonNull Context context) {
       super.onAttach(context);

       // TODO (2): Start trace recording as soon as the Fragment is attached to its host Activity.
       fragmentLoadTrace = FirebasePerformance.startTrace("TestFragment-LoadTime");
   }
  1. Registriere das FirstDrawListener im onViewCreated()-Callback. Stoppen Sie dann, ähnlich wie im Aktivitätsbeispiel, den Trace in onDrawingFinish().

TestFragment.java

@Override
public void onViewCreated(@NonNull View mainView, Bundle savedInstanceState) {
   super.onViewCreated(mainView, savedInstanceState);

   // ...

   // TODO (3): Register the callback to listen for first frame rendering (see
   //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when view drawing is
   //  finished.
   FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {

       @Override
       public void onDrawingStart() {
           // In practice you can also record this event separately
       }

       @Override
       public void onDrawingFinish() {
           // This is when the Fragment UI is completely drawn on the screen
           fragmentLoadTrace.stop();
       }
   });
  1. Führen Sie die App noch einmal aus. Filtern Sie dann den Logcat nach Logging trace metric. Tippe auf die Schaltfläche LOAD FRAGMENT und suche nach Protokollen wie unten:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Glückwunsch! Sie haben die Ladezeit eines Fragments erfolgreich gemessen und die Daten an Firebase Performance Monitoring gemeldet. Wir sehen uns den aufgezeichneten Messwert später in diesem Codelab in der Firebase Console an.

7. Bildschirmrendering und langsame/eingefrorene Frames

Beim UI-Rendering wird ein Frame aus Ihrer App generiert und auf dem Bildschirm dargestellt. Damit die Interaktion eines Nutzers mit Ihrer App reibungslos verläuft, sollte Ihre App Frames in weniger als 16 ms rendern, um 60 Bilder pro Sekunde zu erreichen. Warum sind es 60 fps? Wenn die Benutzeroberfläche Ihrer App langsam gerendert wird, wird das System gezwungen, Frames zu überspringen, und der Nutzer nimmt ein Ruckeln in Ihrer App wahr. Wir nennen dies Jack.

Eingefrorene Frames sind UI-Frames, deren Rendering länger als 700 ms dauert. Diese Verzögerung stellt ein Problem dar, da Ihre App während des Renderings des Frames fast eine ganze Sekunde lang nicht auf Nutzereingaben reagiert.

8. Langsame/eingefrorene Frames eines Fragments messen

Mit Firebase Performance Monitoring werden automatisch langsame/eingefrorene Frames für eine Aktivität erfasst (nur, wenn sie hardwarebeschleunigt ist). Für Fragmente ist diese Funktion derzeit jedoch nicht verfügbar. Die langsamen/eingefrorenen Frames eines Fragments werden als langsame/eingefrorene Frames für die gesamte Activity zwischen den onFragmentAttached()- und onFragmentDetached()-Callbacks im Lebenszyklus des Fragments definiert.

In Anlehnung an die AppStateMonitor-Klasse (die Teil des Performance Monitoring SDK ist, das für die Aufzeichnung von Bildschirm-Traces für Aktivitäten verantwortlich ist), haben wir die ScreenTrace-Klasse implementiert (Teil dieses Codelab-Quellcode-Repositorys). Die ScreenTrace-Klasse kann mit dem Lebenszyklus-Callback der Aktivität FragmentManager verknüpft werden, um langsame/eingefrorene Frames zu erfassen. Diese Klasse bietet zwei öffentliche APIs:

  • recordScreenTrace(): Startet die Aufzeichnung eines Bildschirm-Traces
  • sendScreenTrace(): Beendet die Aufzeichnung eines Bildschirm-Trace und fügt benutzerdefinierte Messwerte hinzu, um die Anzahl der Frames insgesamt, langsamer und eingefrorener Frames zu protokollieren

Wenn Sie diese benutzerdefinierten Messwerte anhängen, können Bildschirmaufzeichnungen für Fragmente genauso wie Bildschirmaufzeichnungen für eine Aktivität behandelt und zusammen mit anderen Bildschirm-Rendering-Aufzeichnungen im Dashboard „Leistung“ der Firebase Console angezeigt werden.

So protokollieren Sie Bildschirm-Traces für Ihr Fragment:

  1. Initialisieren Sie die ScreenTrace-Klasse in Ihrer Aktivität, die das Fragment hostet.

MainActivity.java

// Declare the Fragment tag
private static final String FRAGMENT_TAG = TestFragment.class.getSimpleName();

// TODO (1): Declare the ScreenTrace variable.
private ScreenTrace screenTrace;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // TODO (2): Initialize the ScreenTrace variable.
    screenTrace = new ScreenTrace(this, FRAGMENT_TAG);

    // ...
}
  1. Registriere dich beim Laden des Fragments für FragmentLifecycleCallbacks und überschreibe die onFragmentAttached()- und onFragmentDetached()-Callbacks. Wir haben das für Sie erledigt. Sie müssen die Aufzeichnung von Bildschirmaufzeichnungen im onFragmentAttached()-Callback starten und im onFragmentDetached()-Callback beenden.

MainActivity.java

private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
       new FragmentManager.FragmentLifecycleCallbacks() {

           @Override
           public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
               super.onFragmentAttached(fm, f, context);

               // TODO (3): Start recording the screen traces as soon as the Fragment is
               //  attached to its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.recordScreenTrace();
               }
           }

           @Override
           public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
               super.onFragmentDetached(fm, f);

               // TODO (4): Stop recording the screen traces as soon as the Fragment is
               //  detached from its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.sendScreenTrace();
               }

               // Unregister Fragment lifecycle callbacks after the Fragment is detached
               fm.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks);
           }
       };
  1. Starten Sie die App noch einmal und tippen Sie dann auf die Schaltfläche LOAD FRAGMENT. Warten Sie einige Sekunden und klicken Sie dann in der unteren Navigationsleiste auf das back button.

Filtern Sie den Logcat mit „Logging trace metric“ und suchen Sie dann nach Protokollen wie den folgenden:

I/FirebasePerformance: Logging trace metric: _st_MainActivity-TestFragment (duration: XXXms)

Filtern Sie den Logcat mit „FireperfViews“ und suchen Sie dann nach Protokollen wie dem folgenden:

D/FireperfViews: sendScreenTrace MainActivity-TestFragment, name: _st_MainActivity-TestFragment, total_frames: XX, slow_frames: XX, frozen_frames: XX

🎉 Glückwunsch! Sie haben die langsamen/eingefrorenen Frames für ein Fragment gemessen und diese Daten an Firebase Performance Monitoring gesendet. Wir sehen uns die aufgezeichneten Messwerte später in diesem Codelab in der Firebase Console an.

9. Messwerte in der Firebase Console prüfen

  1. Klicken Sie in Logcat auf die Firebase Console-URL, um die Detailseite eines Logs aufzurufen. ceb9d5ba51bb6e89.jpeg

Alternativ können Sie in der Firebase Console das Projekt mit Ihrer App auswählen. Suchen Sie im linken Bereich den Link Release & Überwachen und dann auf Leistung.

  • Scrollen Sie auf dem Haupt-Tab Dashboard nach unten zur Traces-Tabelle und klicken Sie dann auf den Tab Benutzerdefinierte Traces. In dieser Tabelle sehen Sie die zuvor hinzugefügten benutzerdefinierten Code-Traces sowie einige vordefinierte Traces, z. B. den _app_start-Trace.
  • Suchen Sie die beiden benutzerdefinierten Codetraces TestActivity-LoadTime und TestFragment-LoadTime. Klicken Sie für einen Eintrag auf die Dauer, um weitere Details zu den erhobenen Daten aufzurufen.

a0d8455c5269a590.png

  1. Auf der Detailseite für den benutzerdefinierten Code-Trace werden Informationen zur Dauer des Trace (d.h. die gemessene Ladezeit) angezeigt.

5e92a307b7410d8b.png

  1. Sie können sich auch die Leistungsdaten für Ihren benutzerdefinierten Bildschirmaufruf ansehen.
  • Kehren Sie zum Haupttab Dashboard zurück, scrollen Sie nach unten zur Traces-Tabelle und klicken Sie auf den Tab Bildschirmrendering. In dieser Tabelle sehen Sie die benutzerdefinierten Bildschirmaufzeichnungen, die wir zuvor hinzugefügt haben, sowie alle vordefinierten Bildschirmaufzeichnungen, z. B. die MainActivity-Aufzeichnung.
  • Suchen Sie Ihren benutzerdefinierten Bildschirm-Trace, MainActivity-TestFragment. Klicken Sie auf den Trace-Namen, um die aggregierten Daten zu langsamem Rendering und eingefrorenen Frames aufzurufen.

ee7890c7e2c28740.png

10. Glückwunsch

Glückwunsch! Sie haben mithilfe von Firebase Performance Monitoring die Ladezeit und die Bildschirm-Rendering-Leistung einer Aktivität und eines Fragments erfolgreich gemessen.

Das hast du erreicht

Nächste Schritte

Firebase Performance bietet neben benutzerdefinierten Traces noch weitere Möglichkeiten zur Leistungsmessung Ihrer App. Es werden automatisch App-Startzeit, App-Leistung im Vordergrund und App-Leistung im Hintergrund gemessen. Als Nächstes überprüfen Sie diese Messwerte in der Firebase Console.

Firebase Performance bietet außerdem automatisches Monitoring von HTTP/S-Netzwerkanfragen. Damit können Sie Netzwerkanfragen ganz einfach instrumentieren, ohne eine einzige Codezeile schreiben zu müssen. Können Sie einige Netzwerkanfragen von Ihrer App senden und die Messwerte in der Firebase Console finden?

Bonus

Da Sie jetzt wissen, wie Sie die Ladezeit und die Bildschirmdarstellungsleistung Ihrer Aktivität/Ihres Fragments mithilfe benutzerdefinierter Code-Traces messen, können Sie unseren Open-Source-Code-Base untersuchen, um zu sehen, ob Sie diese Messwerte direkt für jede Aktivität/Fragment erfassen können, die Teil der App ist. Wenn Sie möchten, können Sie die PR-Datei auch gern senden.

11. Bonus-Lerninhalte

Wenn du weißt, was während des Ladens einer Aktivität passiert, kannst du die Leistungsmerkmale deiner App besser nachvollziehen. In einem früheren Schritt haben wir allgemein beschrieben, was während des Ladens einer Aktivität passiert. Im folgenden Diagramm werden die einzelnen Phasen jedoch viel ausführlicher beschrieben.

cd61c1495fad7961.png