Misura il tempo di caricamento e il rendering dello schermo con Firebase Performance Monitoring

1. Introduzione

Ultimo aggiornamento: 2021-03-11

Perché dobbiamo misurare le prestazioni di Views?

Le visualizzazioni sono una parte fondamentale delle applicazioni Android che influiscono direttamente sull'esperienza dell'utente. Ad esempio, l'attività o il frammento contiene l'interfaccia utente che contiene i componenti di visualizzazione con cui gli utenti interagiscono. Gli utenti non sono in grado di vedere l'intero contenuto dell'interfaccia utente finché non è completamente disegnato sullo schermo. Le schermate lente e bloccate comprometteranno direttamente l'interazione dell'utente con la tua app e creeranno un'esperienza utente negativa.

Firebase Performance Monitoring non fornisce queste metriche delle prestazioni pronte all'uso?

Firebase Performance Monitoring acquisisce automaticamente alcuni dati sulle prestazioni pronti all'uso, come l'ora di inizio dell'app (ad es. il tempo di caricamento solo per la prima attività) e le prestazioni di rendering dello schermo (ad es. frame lenti e bloccati per le attività ma non per frammenti). Tuttavia, le app del settore di solito non hanno molte attività ma piuttosto un'attività e più frammenti. Inoltre, molte app di solito implementano le proprie viste personalizzate per casi d'uso più complessi. Quindi è spesso utile capire come misurare il tempo di caricamento e le prestazioni di rendering dello schermo di attività e frammenti strumentando tracce di codice personalizzate nell'app. Puoi facilmente estendere questo codelab per misurare le prestazioni dei componenti della vista personalizzata.

Cosa imparerai

  • Come aggiungere il monitoraggio delle prestazioni di Firebase a un'app Android
  • Comprendere il caricamento di un'attività o di un frammento
  • Come strumentare tracce di codice personalizzato per misurare il tempo di caricamento di un'attività o di un frammento
  • Comprendere il rendering dello schermo e cos'è un frame lento/congelato
  • Come strumentare tracce di codice personalizzato con metriche per registrare schermate lente/congelate
  • Come visualizzare le metriche raccolte nella console Firebase

Di cosa avrai bisogno

  • Android Studio 4.0 o versioni successive
  • Un dispositivo/emulatore Android
  • Java versione 8 o successiva

2. Prepararsi

Ottieni il codice

Eseguire i comandi seguenti per clonare il codice di esempio per questo codelab. Questo creerà una cartella chiamata codelab-measure-android-view-performance sulla tua macchina:

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

Se non hai git sulla tua macchina, puoi anche scaricare il codice direttamente da GitHub.

Importa il progetto measure-view-performance-start in Android Studio. Probabilmente vedrai alcuni errori di compilazione o forse un avviso su un file google-services.json mancante. Lo correggeremo nella prossima sezione di questo passaggio.

In questo codelab, utilizzeremo il plug-in Firebase Assistant per registrare la nostra app Android con un progetto Firebase e aggiungere i file di configurazione, i plug-in e le dipendenze di Firebase necessari al nostro progetto Android, il tutto da Android Studio !

Collega la tua app a Firebase

  1. Vai su Android Studio / Guida > Verifica aggiornamenti per assicurarti di utilizzare le ultime versioni di Android Studio e Firebase Assistant.
  2. Seleziona Strumenti > Firebase per aprire il riquadro dell'assistente .

e791bed0999db1e0.png

  1. Scegli Monitoraggio delle prestazioni da aggiungere alla tua app, quindi fai clic su Inizia con il monitoraggio delle prestazioni .
  2. Fai clic su Connetti a Firebase per connettere il tuo progetto Android con Firebase (questo aprirà la console Firebase nel tuo browser) .
  3. Nella console Firebase, fai clic su Aggiungi progetto , quindi inserisci il nome di un progetto Firebase (se hai già un progetto Firebase, puoi invece selezionare quel progetto esistente) . Fai clic su Continua e accetta i termini per creare il progetto Firebase e una nuova app Firebase.
  4. Successivamente dovresti vedere una finestra di dialogo per collegare la tua nuova app Firebase al tuo progetto Android Studio.

42c498d28ead2b77.png

  1. Di nuovo in Android Studio, nel riquadro Assistente , dovresti vedere la conferma che la tua app è connessa a Firebase.

dda8bdd9488167a0.png

Aggiungi il monitoraggio delle prestazioni alla tua app

Nel riquadro Assistente in Android Studio, fai clic su Aggiungi monitoraggio delle prestazioni alla tua app .

Dovresti vedere una finestra di dialogo per accettare modifiche dopo la quale Android Studio dovrebbe sincronizzare la tua app per garantire che tutte le dipendenze necessarie siano state aggiunte.

9b58145acc4be030.png

Infine, dovresti vedere il messaggio di successo nel riquadro Assistente in Android Studio che tutte le dipendenze sono impostate correttamente.

aa0d46fc944e0c0b.png

Come passaggio aggiuntivo, abilita la registrazione del debug seguendo le istruzioni nel passaggio "(Facoltativo) Abilita la registrazione del debug". Le stesse istruzioni sono disponibili anche nella documentazione pubblica .

3. Esegui l'app

Se hai integrato correttamente la tua app con Performance Monitoring SDK, il progetto dovrebbe ora essere compilato. In Android Studio, fai clic su Esegui > Esegui "app" per creare ed eseguire l'app sul tuo dispositivo/emulatore Android connesso.

L'app ha due pulsanti che ti portano a un'attività e a un frammento corrispondenti, come questo:

410d8686b4f45c33.png

Nei passaggi seguenti di questo codelab, imparerai come misurare il tempo di caricamento e le prestazioni di rendering dello schermo della tua attività o del tuo frammento.

4. Comprendere il caricamento di un'attività o di un frammento

In questo passaggio impareremo cosa sta facendo il sistema durante il caricamento di un'attività o di un frammento.

Comprendere il caricamento di un'attività

Per un'Attività, il tempo di caricamento è definito come il tempo che inizia da quando l'oggetto Activity viene creato fino a quando il Primo Frame è completamente disegnato sullo schermo ( questo è quando l'utente vedrà l'interfaccia utente completa per l'Attività per il primo tempo ). Per misurare se la tua app è completamente disegnata, puoi utilizzare il metodo reportFullyDrawn() per misurare il tempo trascorso tra l'avvio dell'applicazione e la visualizzazione completa di tutte le risorse e visualizzare le gerarchie.

A un livello elevato, quando l'app chiama startActivity(Intent) , il sistema esegue automaticamente i processi seguenti. Ogni processo richiede tempo per essere completato, che si aggiunge alla durata del tempo tra la creazione dell'attività e quando l'utente vede l'interfaccia utente per l'attività sul proprio schermo.

c20d14b151549937.png

Comprendere il caricamento di un frammento

Simile all'attività, il tempo di caricamento di un frammento è definito come il tempo che inizia da quando il frammento viene attaccato alla sua attività host fino a quando il primo fotogramma per la vista del frammento è completamente disegnato sullo schermo.

5. Misurare il tempo di caricamento di un'attività

I ritardi nel primo frame possono portare a un'esperienza utente negativa, quindi è importante capire quanto ritardo di caricamento iniziale stanno riscontrando i tuoi utenti. È possibile strumentare una traccia di codice personalizzata per misurare questo tempo di caricamento:

  1. Avviare la traccia del codice personalizzato (denominata TestActivity-LoadTime ) nella classe Activity non appena viene creato l'oggetto Activity.

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. Eseguire l'override del callback onCreate() e ottenere la vista aggiunta dal metodo setContentView() .
@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. Abbiamo incluso un'implementazione di FistDrawListener , che ha due callback: onDrawingStart() e onDrawingFinish() (vedi la sezione successiva di seguito per maggiori dettagli su FirstDrawListener e cosa può influire sulle sue prestazioni) . Registra il FirstDrawListener alla fine del callback onCreate() di Activity. Dovresti interrompere viewLoadTrace nel callback onDrawingFinish() .

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. Esegui nuovamente l'app. Quindi, filtra il logcat con " Metrica di traccia di registrazione ". Tocca il pulsante LOAD ACTIVITY e cerca i registri come di seguito:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Complimenti! Hai misurato con successo il tempo di caricamento di un'attività e segnalato i dati a Firebase Performance Monitoring. Vedremo la metrica registrata nella console Firebase più avanti in questo codelab.

Scopo di FirstDrawListener

Nella sezione appena sopra, abbiamo registrato un FirstDrawListener . Lo scopo di FirstDrawListener è misurare quando il primo frame ha iniziato e terminato il disegno.

Implementa ViewTreeObserver.OnDrawListener e sovrascrive il callback onDraw() che viene richiamato quando l'albero della vista sta per essere disegnato. Quindi esegue il wrapping del risultato per fornire due callback di utilità onDrawingStart() e onDrawingFinish() .

Il codice completo per FirstDrawListener può essere trovato nel codice sorgente di questo codelab .

6. Misurare il tempo di caricamento di un frammento

La misurazione del tempo di caricamento di un frammento è simile a come lo misuriamo per un'attività, ma con alcune piccole differenze. Ancora una volta, strumentiamo una traccia di codice personalizzata :

  1. Sovrascrivi il callback onAttach() e inizia a registrare il tuo fragmentLoadTrace . Chiameremo questa traccia Test-Fragment-LoadTime .

Come spiegato in un passaggio precedente, l'oggetto Fragment può essere creato in qualsiasi momento, ma diventa attivo solo quando è collegato all'attività host.

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. Registra il FirstDrawListener nel callback onViewCreated() . Quindi, in modo simile all'esempio Activity, interrompere la traccia 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. Esegui nuovamente l'app. Quindi, filtra il logcat con " Metrica di traccia di registrazione ". Tocca il pulsante LOAD FRAGMENT e cerca i registri come di seguito:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Complimenti! Hai misurato con successo il tempo di caricamento di un frammento e segnalato i dati a Firebase Performance Monitoring. Vedremo la metrica registrata nella console Firebase più avanti in questo codelab.

7. Comprendere il rendering dello schermo e cos'è un frame lento/congelato

Il rendering dell'interfaccia utente è l'atto di generare un frame dalla tua app e visualizzarlo sullo schermo. Per garantire che l'interazione di un utente con la tua app sia fluida, la tua app deve eseguire il rendering di fotogrammi in meno di 16 ms per ottenere 60 fotogrammi al secondo ( perché 60 fps? ). Se la tua app soffre di un rendering lento dell'interfaccia utente, il sistema è costretto a saltare i frame e l'utente percepirà la balbuzie nella tua app. Lo chiamiamo jank .

Allo stesso modo, i frame bloccati sono frame dell'interfaccia utente che richiedono più di 700 ms per il rendering. Questo ritardo è un problema perché la tua app sembra bloccata e non risponde all'input dell'utente per quasi un intero secondo mentre il frame è in fase di rendering.

8. Misurare i fotogrammi Slow/Frozen di un frammento

Firebase Performance Monitoring acquisisce automaticamente i frame lenti/congelati per un'attività ( ma solo se è con accelerazione hardware ). Tuttavia, questa funzione non è attualmente disponibile per i frammenti. I frame lenti/congelati di un frammento sono definiti come i frame lenti/congelati per l'intera attività tra i onFragmentAttached() e onFragmentDetached() nel ciclo di vita del frammento.

Prendendo la motivazione dalla classe AppStateMonitor ( che fa parte dell'SDK di monitoraggio delle prestazioni responsabile della registrazione delle tracce dello schermo per Activity ), abbiamo implementato la classe ScreenTrace ( che fa parte di questo repository di codice sorgente codelab ). La classe ScreenTrace può essere collegata al callback del ciclo di vita di FragmentManager dell'attività per acquisire frame lenti/congelati. Questa classe fornisce due API pubbliche:

  • recordScreenTrace() : avvia la registrazione di una traccia dello schermo
  • sendScreenTrace() : interrompe la registrazione di una traccia dello schermo e allega metriche personalizzate per registrare i conteggi di fotogrammi totali, lenti e bloccati

Allegando queste metriche personalizzate, le tracce dello schermo per i frammenti possono essere gestite allo stesso modo delle tracce dello schermo per un'attività e possono essere visualizzate insieme ad altre tracce di rendering dello schermo nel dashboard delle prestazioni della console Firebase.

Ecco come registrare le tracce dello schermo per il tuo frammento:

  1. Inizializza la classe ScreenTrace nella tua attività che ospita il frammento.

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. Quando carichi il tuo frammento, registrati per FragmentLifecycleCallbacks e sovrascrivi i onFragmentAttached() e onFragmentDetached() . L'abbiamo fatto per te. È necessario avviare la registrazione delle tracce dello schermo nel callback onFragmentAttached() e interrompere la registrazione nel callback onFragmentDetached() .

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. Esegui nuovamente l'app. Quindi, tocca il pulsante LOAD FRAGMENT . Attendi qualche secondo, quindi fai clic sul back button nella barra di navigazione in basso.

Filtra il logcat con " Logging trace metric ", quindi cerca i log come di seguito:

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

Filtra il logcat con " FireperfViews ", quindi cerca i log come di seguito:

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

🎉 Complimenti! Hai misurato con successo i frame lenti/congelati per un frammento e segnalato i dati al monitoraggio delle prestazioni di Firebase. Vedremo le metriche registrate nella console Firebase più avanti in questo codelab.

9. Controlla le metriche nella console Firebase

  1. Nel logcat, fai clic sull'URL della console Firebase per visitare la pagina dei dettagli per una traccia. ceb9d5ba51bb6e89.jpeg

In alternativa, nella console Firebase , seleziona il progetto che contiene la tua app. Nel pannello di sinistra, individua la sezione Rilascio e monitoraggio , quindi fai clic su Prestazioni .

  • Nella scheda Dashboard principale, scorri verso il basso fino alla tabella delle tracce, quindi fai clic sulla scheda Tracce personalizzate . In questa tabella vedrai le tracce di codice personalizzate che abbiamo aggiunto in precedenza più alcune tracce pronte all'uso, come _app_start trace.
  • Trova le tue due tracce di codice personalizzate, TestActivity-LoadTime e TestFragment-LoadTime . Fare clic su Durata per uno dei due per visualizzare maggiori dettagli sui dati raccolti.

a0d8455c5269a590.png

  1. La pagina dei dettagli per la traccia del codice personalizzato mostra le informazioni sulla durata della traccia (ovvero, il tempo di caricamento misurato).

5e92a307b7410d8b.png

  1. Puoi anche visualizzare i dati sulle prestazioni per la traccia dello schermo personalizzata.
  • Torna alla scheda Dashboard principale, scorri verso il basso fino alla tabella delle tracce, quindi fai clic sulla scheda Rendering dello schermo . In questa tabella vedrai le tracce dello schermo personalizzate che abbiamo aggiunto in precedenza più eventuali tracce dello schermo predefinite , come la traccia MainActivity .
  • Trova la traccia dello schermo personalizzata, MainActivity-TestFragment . Fare clic sul nome della traccia per visualizzare i dati aggregati di rendering lento e fotogrammi bloccati.

ee7890c7e2c28740.png

10. Congratulazioni

Congratulazioni! Hai misurato con successo il tempo di caricamento e le prestazioni di rendering dello schermo di un'attività e di un frammento utilizzando Firebase Performance Monitoring!

Quello che hai realizzato

Qual è il prossimo

Firebase Performance offre più modi per misurare le prestazioni della tua app oltre alla traccia personalizzata. Misura automaticamente il tempo di avvio dell'app, i dati sulle prestazioni dell'app in primo piano e in background . È ora che tu controlli queste metriche nella console di Firebase .

Inoltre, Firebase Performance offre il monitoraggio automatico delle richieste di rete HTTP/S . In questo modo puoi facilmente strumentare le richieste di rete senza scrivere una sola riga di codice. Puoi provare a inviare alcune richieste di rete dalla tua app e trovare le metriche nella console Firebase ?

Bonus

Ora che sai come misurare il tempo di caricamento e le prestazioni di rendering dello schermo della tua attività/frammento utilizzando tracce di codice personalizzate, puoi esplorare la nostra base di codice open source per vedere se riesci a catturare quelle metriche fuori dagli schemi per qualsiasi attività/frammento fa parte dell'app? Sentiti libero di inviare il PR se lo desideri :-)

11. Apprendimento bonus

Capire cosa sta succedendo durante il caricamento di un'attività ti aiuterà a comprendere meglio le caratteristiche delle prestazioni della tua app. In una fase precedente, abbiamo descritto ad alto livello cosa accade durante il caricamento di un'attività, ma il diagramma seguente descrive ciascuna fase in modo molto più dettagliato.

cd61c1495fad7961.png