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

1. Introduzione

Ultimo aggiornamento: 2021-03-11

Perché dobbiamo misurare la performance delle Views?

Le visualizzazioni sono una parte fondamentale delle applicazioni Android che influiscono direttamente sull'esperienza dell'utente. Ad esempio, la tua attività o frammento contiene l'interfaccia utente che contiene i componenti di visualizzazione con cui interagiscono gli utenti. Gli utenti non sono in grado di visualizzare l'intero contenuto dell'interfaccia utente finché non viene 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 prestazionali immediatamente?

Firebase Performance Monitoring acquisisce automaticamente alcuni dati sulle prestazioni, come l'ora di inizio dell'app (ovvero il tempo di caricamento solo per la prima attività) e le prestazioni di rendering dello schermo (ovvero fotogrammi lenti e bloccati per le attività ma non per Frammenti). Tuttavia, le app di settore in genere non hanno molte attività, ma piuttosto un'attività e più frammenti. Inoltre, molte app solitamente implementano le proprie visualizzazioni personalizzate per casi d'uso più complessi. Pertanto è spesso utile capire come misurare il tempo di caricamento e le prestazioni di rendering dello schermo sia delle attività che dei frammenti strumentando tracce di codice personalizzate nella tua app. Puoi estendere facilmente questo codelab per misurare le prestazioni dei componenti di visualizzazione personalizzata.

Cosa imparerai

  • Come aggiungere Firebase Performance Monitoring a un'app Android
  • Comprendere il caricamento di un'attività o di un frammento
  • Come strumentare le tracce del codice personalizzato per misurare il tempo di caricamento di un'attività o di un frammento
  • Comprensione del rendering dello schermo e cos'è un fotogramma lento/congelato
  • Come dotare le tracce del codice personalizzato con metriche per registrare schermate lente/bloccate
  • Come visualizzare i parametri raccolti nella console Firebase

Di cosa avrai bisogno

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

2. Preparazione

Ottieni il codice

Esegui i seguenti comandi per clonare il codice di esempio per questo codelab. Questo creerà una cartella chiamata codelab-measure-android-view-performance sul tuo computer:

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

Se non hai Git sul tuo computer, 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 relativo a un file google-services.json mancante. Lo correggeremo nella sezione successiva 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 Firebase necessari al nostro progetto Android, il tutto da Android Studio !

Collega la tua app a Firebase

  1. Vai su Android Studio / Guida > Controlla aggiornamenti per assicurarti di utilizzare le versioni più recenti di Android Studio e Firebase Assistant.
  2. Seleziona Strumenti > Firebase per aprire il riquadro Assistente .

e791bed0999db1e0.png

  1. Scegli il 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 il 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 connettere la tua nuova app Firebase al tuo progetto Android Studio.

42c498d28ead2b77.png

  1. Tornando 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 visualizzare una finestra di dialogo per Accettare le modifiche , dopodiché 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, abilitare 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 all'attività e al frammento corrispondenti, in questo modo:

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 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 intercorre da quando viene creato l'oggetto Attività fino a quando il primo fotogramma non viene completamente disegnato sullo schermo ( questo è il momento in cui l'utente vedrà l'interfaccia utente completa per l'attività per la prima volta 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.

Ad alto livello, quando l'app chiama startActivity(Intent) , il sistema esegue automaticamente i seguenti processi. Il completamento di ogni processo richiede tempo, che si aggiunge alla durata di tempo tra la creazione dell'attività e il momento in cui l'utente visualizza l'interfaccia utente dell'attività sullo schermo.

c20d14b151549937.png

Comprendere il caricamento di un frammento

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

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

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

  1. Avvia 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. Sostituisci il callback onCreate() e ottieni 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() (vedere la sezione successiva di seguito per maggiori dettagli su FirstDrawListener e cosa può influire sulle sue prestazioni) . Registra FirstDrawListener alla fine del callback onCreate() dell'attività. 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 " Logging trace metric ". Tocca il pulsante LOAD ACTIVITY e cerca i registri come di seguito:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Complimenti! Hai misurato correttamente 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 fotogramma è iniziato e ha finito di disegnare.

Implementa ViewTreeObserver.OnDrawListener e sovrascrive il callback onDraw() che viene richiamato quando l'albero della vista sta per essere disegnato. Quindi esegue il wrapper 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. Misura il tempo di caricamento di un frammento

Misurare il tempo di caricamento di un frammento è simile a come lo misuriamo per un'attività ma con alcune piccole differenze. Ancora una volta, strumenteremo una traccia del codice personalizzato :

  1. Sostituisci 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 alla sua 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 FirstDrawListener nel callback onViewCreated() . Quindi, in modo simile all'esempio Activity, interrompi 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 " Logging trace metric ". Tocca il pulsante LOAD FRAGMENT e cerca i registri come di seguito:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Complimenti! Hai misurato correttamente 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 fotogramma 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 dei fotogrammi in meno di 16 ms per raggiungere 60 fotogrammi al secondo ( perché 60 fps? ). Se la tua app soffre di un rendering dell'interfaccia utente lento, il sistema è costretto a saltare i fotogrammi e l'utente percepirà uno stuttering nella tua app. Lo chiamiamo jank .

Allo stesso modo, i frame congelati 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 secondo intero durante il rendering del frame.

8. Misura i fotogrammi lenti/congelati di un frammento

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

Prendendo spunto dalla classe AppStateMonitor ( che fa parte dell'SDK Performance Monitoring responsabile della registrazione delle tracce dello schermo per Activity ), abbiamo implementato la classe ScreenTrace ( che fa parte di questo repository del codice sorgente codelab ). La classe ScreenTrace può essere collegata al callback del ciclo di vita di FragmentManager dell'attività per acquisire fotogrammi 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 dei fotogrammi totali, lenti e congelati

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 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 callback onFragmentAttached() e onFragmentDetached() . Lo 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 correttamente i frame lenti/bloccati per un frammento e segnalato i dati a Firebase Performance Monitoring. Vedremo i parametri registrati 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 Rilascia e monitora , quindi fai clic su Prestazioni .

  • Nella scheda principale della Dashboard , scorri verso il basso fino alla tabella delle tracce, quindi fai clic sulla scheda Tracce personalizzate . In questa tabella vedrai le tracce del codice personalizzato che abbiamo aggiunto in precedenza oltre ad alcune tracce predefinite , come la traccia _app_start .
  • Trova le due tracce di codice personalizzate, TestActivity-LoadTime e TestFragment-LoadTime . Fare clic sulla Durata di uno dei due per visualizzare maggiori dettagli sui dati raccolti.

a0d8455c5269a590.png

  1. La pagina dei dettagli per la traccia del codice personalizzato mostra 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 principale della dashboard , 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 del rendering lento e dei fotogrammi congelati.

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.

Ciò che hai realizzato

Qual è il prossimo

Firebase Performance offre più modalità di misurazione delle 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 dell'app in background . È giunto il momento di controllare queste metriche nella console Firebase .

Inoltre, Firebase Performance offre il monitoraggio automatico delle richieste di rete HTTP/S . In questo modo puoi facilmente gestire 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 ad acquisire tali metriche immediatamente per qualsiasi attività/frammento fa parte dell'app? Sentiti libero di inviare il PR se lo desideri :-)

11. Apprendimento bonus

Capire cosa succede durante il caricamento di un'attività ti aiuterà a comprendere meglio le caratteristiche prestazionali della tua app. In un passaggio 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