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

1. Introduzione

Ultimo aggiornamento: 2021-03-11

Perché dobbiamo misurare il rendimento delle visualizzazioni?

Le visualizzazioni sono un elemento chiave delle applicazioni per Android che influiscono direttamente sull'esperienza utente. Ad esempio, l'attività o il frammento contiene l'interfaccia utente che contiene i componenti View con cui gli utenti interagiscono. Gli utenti non possono vedere l'intero contenuto dell'interfaccia utente finché non viene completamente disegnata sullo schermo. Schermate lente e bloccate compromettono direttamente l'interazione dell'utente con la tua app e creano un'esperienza utente negativa.

Firebase Performance Monitoring non fornisce già queste metriche sul rendimento?

Firebase Performance Monitoring acquisisce automaticamente alcuni dati sulle prestazioni, come l'ora di avvio dell'app (ovvero il tempo di caricamento solo per la prima attività) e le prestazioni di rendering dello schermo (ovvero frame lenti e congelati per le attività, ma non per i frammenti). Tuttavia, le app di settore di solito non hanno molte attività, ma un'unica attività e più frammenti. Inoltre, molte app di solito 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 delle attività e dei frammenti utilizzando tracce di codice personalizzate nella tua app. Puoi facilmente estendere questo codelab per misurare il rendimento dei componenti Visualizzazione personalizzata.

Cosa imparerai a fare

  • Aggiungere Firebase Performance Monitoring a un'app per Android
  • Informazioni sul caricamento di un'attività o di un frammento
  • Come eseguire l'instrumentazione delle 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/bloccato
  • Come instrumentare le tracce di codice personalizzate con le metriche per registrare le schermate lente/bloccate
  • Come visualizzare le metriche raccolte nella console Firebase

Che cosa ti serve

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

2. Preparazione

Ottieni il codice

Esegui i seguenti comandi per clonare il codice di esempio per questo codelab. Verrà creata una cartella denominata 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 un avviso relativo a un file google-services.json mancante. Correggeremo il problema nella sezione successiva di questo passaggio.

In questo codelab, useremo il plug-in dell'Assistente Firebase per registrare la nostra app Android con un progetto Firebase e aggiungeremo i file di configurazione, i plug-in e le dipendenze di Firebase necessari al progetto Android, tutto da Android Studio.

Collega la tua app a Firebase

  1. Vai ad Android Studio/Guida > Verifica la disponibilità di aggiornamenti per assicurarti di utilizzare le ultime versioni di Android Studio e dell'Assistente Firebase.
  2. Seleziona Strumenti > Firebase per aprire il riquadro Assistente.

E791bed0999db1e0.png

  1. Scegli Performance Monitoring da aggiungere alla tua app, poi fai clic su Inizia a utilizzare Performance Monitoring.
  2. Fai clic su Connetti a Firebase per collegare il tuo progetto Android a Firebase (si aprirà la console Firebase nel browser).
  3. Nella console Firebase, fai clic su Aggiungi progetto e inserisci un nome per il progetto Firebase (se ne hai già uno, puoi selezionare il progetto esistente). Fai clic su Continua e accetta i termini per creare il progetto Firebase e una nuova app Firebase.
  4. A questo punto dovresti visualizzare una finestra di dialogo per collegare la nuova app Firebase al tuo progetto Android Studio.

42c498d28ead2b77.png

  1. Tornando ad 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 Performance Monitoring alla tua app.

Dovresti visualizzare una finestra di dialogo Accetta modifiche, dopodiché Android Studio deve sincronizzare l'app per assicurarsi che siano state aggiunte tutte le dipendenze necessarie.

9b58145acc4be030.png

Infine, nel riquadro Assistente di Android Studio dovresti visualizzare il messaggio di successo che indica che tutte le dipendenze sono configurate correttamente.

aa0d46fc944e0c0b.png

Come passaggio aggiuntivo, attiva il logging di debug seguendo le istruzioni riportate nel passaggio "(Facoltativo) Attivare il logging di debug". Le stesse istruzioni sono disponibili anche nella documentazione pubblica.

3. Esegui l'app

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

L'app ha due pulsanti che ti indirizzano a un'attività e a un frammento corrispondenti, come mostrato di seguito:

410d8686b4f45c33.png

Nei seguenti passaggi di questo codelab, imparerai a misurare il tempo di caricamento e le prestazioni di rendering dello schermo dell'attività o del frammento.

4. Informazioni sul 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.

Informazioni sul caricamento di un'attività

Per un'attività, il tempo di caricamento è definito come il tempo che intercorre tra la creazione dell'oggetto Attività e il momento in cui viene disegnato completamente il Primo frame sullo schermo (questo è il momento in cui l'utente vedrà per la prima volta l'UI completa dell'attività). Per misurare se l'app è stata tracciata completamente, puoi utilizzare il metodo reportFullyDrawn() per misurare il tempo trascorso tra l'avvio dell'applicazione e la visualizzazione completa di tutte le risorse e per visualizzare le gerarchie.

A livello generale, quando la tua app chiama startActivity(Intent), il sistema esegue automaticamente i seguenti processi. Il completamento di ogni processo richiede tempo, che si aggiunge al tempo che intercorre tra la creazione dell'attività e il momento in cui l'utente vede la UI dell'attività sullo schermo.

c20d14b151549937.png

Informazioni sul caricamento di un frammento

Come per l'attività, il tempo di caricamento di un frammento è definito come il tempo che inizia dal momento in cui il frammento viene collegato all'attività host fino a quando il primo frame della visualizzazione del frammento non viene completamente visualizzato 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 del caricamento iniziale stanno riscontrando gli utenti. Puoi impostare una traccia di codice personalizzata per misurare questo tempo di caricamento:

  1. Avvia la traccia di codice personalizzata (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. Esegui l'override del callback onCreate()e fai in modo che la vista venga 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() (consulta la sezione successiva per ulteriori dettagli su FirstDrawListener e su cosa può influire sul suo rendimento). Registra il FirstDrawListener alla fine del callback onCreate()dell'attività. Devi 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 di nuovo l'app. Quindi, filtra il logcat con "Metrica di traccia di Logging". Tocca il pulsante LOAD ACTIVITY e cerca i log come quelli che seguono:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Congratulazioni! Hai misurato correttamente il tempo di caricamento di un'attività e hai registrato i dati in Firebase Performance Monitoring. Visualizzeremo la metrica registrata nella Console Firebase più avanti in questo codelab.

Scopo di FirstDrawListener

Nella sezione precedente abbiamo registrato un FirstDrawListener. Lo scopo di FirstDrawListener è misurare quando è iniziato e terminato il disegno del primo frame.

Implementa ViewTreeObserver.OnDrawListener e sostituisce il callback onDraw() che viene invocato quando sta per essere disegnata la struttura ad albero della visualizzazione. Quindi, aggrega il risultato per fornire due callback di utilità onDrawingStart()e onDrawingFinish().

Il codice completo di FirstDrawListener è disponibile 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 quella per un'attività, ma con alcune piccole differenze. Anche in questo caso, strumentalizzeremo una traccia di codice personalizzato:

  1. Ignora 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 viene associato 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 FirstDrawListener nel callback onViewCreated(). Poi, come nell'esempio di attività, 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 di nuovo l'app. Quindi, filtra il logcat con "Metrica traccia log". Tocca il pulsante LOAD FRAGMENT e cerca log come quelli riportati di seguito:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Complimenti! Hai misurato il tempo di caricamento di un frammento e inviato i relativi 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/bloccato

Il rendering dell'interfaccia utente consiste nel generare un frame dalla tua app e mostrarlo sullo schermo. Per garantire che l'interazione di un utente con la tua app sia fluida, la tua app dovrebbe eseguire il rendering dei frame in meno di 16 ms per raggiungere 60 frame al secondo ( perché 60 f/s?). Se il rendering dell'interfaccia utente della tua app è lento, il sistema è costretto a saltare i frame e l'utente percepirà uno sfarfallio nell'app. Questo fenomeno è chiamato jank.

Analogamente, 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 essere bloccata e non risponde all'input dell'utente per quasi un secondo durante il rendering del frame.

8. Misura i frame lenti/bloccati di un frammento

Firebase Performance Monitoring acquisisce automaticamente i frame lenti/congelati per un'attività (ma solo se è con accelerazione hardware). Tuttavia, questa funzionalità non è attualmente disponibile per i frammenti. Per frame lenti/bloccati di un frammento si intendono i frame lenti/bloccati per l'intera attività tra i callback onFragmentAttached() e onFragmentDetached() nel ciclo di vita di un frammento.

Prendendo spunto dalla classe AppStateMonitor (che fa parte dell'SDK Performance Monitoring responsabile della registrazione delle tracce dello schermo per l'Attività), abbiamo implementato la classe ScreenTrace (che fa parte di questo repository di codice sorgente del codelab). La classe ScreenTrace può essere collegata al callback del ciclo di vita di FragmentManager dell'attività per acquisire frame in slow motion/congelati. Questo corso fornisce due API pubbliche:

  • recordScreenTrace(): avvia la registrazione di una traccia dello schermo
  • sendScreenTrace(): interrompe la registrazione di un'analisi dello schermo e collega metriche personalizzate per registrare i conteggi di frame totali, lenti e bloccati.

Se colleghi 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 nella dashboard Prestazioni della Console Firebase.

Per registrare le tracce dello schermo per il frammento:

  1. Inizializza la classe ScreenTrace nell'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 frammento, registrati su FragmentLifecycleCallbacks e sostituisci i callback onFragmentAttached() e onFragmentDetached(). Lo abbiamo fatto per te. Devi avviare la registrazione delle tracce dello schermo nel callback onFragmentAttached() e interromperla 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 di nuovo l'app. Dopodiché tocca il pulsante LOAD FRAGMENT. Attendi qualche secondo, poi fai clic sulla back button nella barra di navigazione in basso.

Filtra logcat con "Metrica traccia di log", quindi cerca log come quelli riportati di seguito:

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

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

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

🎉 Congratulazioni! Hai misurato correttamente i frame lenti/congelati per un frammento e hai registrato questi dati in Firebase Performance Monitoring. Vedremo le metriche registrate nella console Firebase più avanti in questo codelab.

9. Controllare le metriche nella console Firebase

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

In alternativa, nella console Firebase, seleziona il progetto che contiene la tua app. Nel riquadro a sinistra, individua la sezione Release e monitoraggio e fai clic su Rendimento.

  • Nella scheda principale Dashboard, scorri verso il basso fino alla tabella delle tracce e poi fai clic sulla scheda Tracce personalizzate. In questa tabella vengono visualizzate le tracce di codice personalizzate che abbiamo aggiunto in precedenza, oltre ad alcune tracce pronte all'uso, ad esempio la traccia _app_start.
  • Trova le due tracce di codice personalizzate, TestActivity-LoadTime e TestFragment-LoadTime. Fai clic su Durata per uno dei due per visualizzare ulteriori dettagli sui dati raccolti.

a0d8455c5269a590.png

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

5e92a307b7410d8b.png

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

fiore2017.png

10. Complimenti

Complimenti! Hai misurato il tempo di caricamento e il rendimento del rendering dello schermo di un'attività e di un frammento utilizzando Firebase Performance Monitoring.

Obiettivi raggiunti

Passaggi successivi

Oltre all'analisi personalizzata, Firebase Performance offre altri modi per misurare le prestazioni della tua app. Misura automaticamente i dati relativi al tempo di avvio dell'app, all'app in primo piano e alle prestazioni dell'app in background. È 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 gestire facilmente 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 di Firebase?

Bonus

Ora che sai come misurare il tempo di caricamento e le prestazioni di rendering dello schermo dell'attività o del frammento utilizzando tracce di codice personalizzate, puoi esplorare il nostro codebase open source per vedere se riesci ad acquisire queste metriche pronte per l'uso per qualsiasi attività/frammento che fa parte dell'app? Invia pure il PR se vuoi :-)

11. Apprendimento extra

Comprendere cosa succede durante il caricamento di un'attività ti aiuterà a comprendere meglio le caratteristiche di rendimento della tua app. In un passaggio precedente abbiamo descritto a grandi linee cosa succede durante il caricamento di un'attività, ma il seguente diagramma descrive ogni fase in modo molto più dettagliato.

cd61c1495fad7961.png