Mesurez le temps de chargement et le rendu de l'écran avec Firebase Performance Monitoring

1. Introduction

Dernière mise à jour : 2021-03-11

Pourquoi avons-nous besoin de mesurer les performances des vues ?

Les vues sont un élément clé des applications Android qui affectent directement l'expérience utilisateur. Par exemple, votre activité ou fragment contient l'interface utilisateur qui contient les composants View avec lesquels les utilisateurs interagissent. Les utilisateurs ne peuvent pas voir l'intégralité du contenu de l'interface utilisateur tant qu'il n'est pas entièrement dessiné à l'écran. Les écrans lents et gelés nuiront directement à l'interaction de l'utilisateur avec votre application et créeront une mauvaise expérience utilisateur.

La surveillance des performances de Firebase ne fournit-elle pas ces mesures de performances prêtes à l'emploi ?

Firebase Performance Monitoring capture automatiquement certaines données de performances prêtes à l'emploi, telles que l'heure de démarrage de votre application (c'est-à-dire le temps de chargement de votre première activité uniquement) et les performances de rendu d'écran (c'est-à-dire des images lentes et gelées pour les activités mais pas pour fragments). Cependant, les applications de l'industrie n'ont généralement pas beaucoup d'activités, mais plutôt une activité et plusieurs fragments. En outre, de nombreuses applications implémentent généralement leurs propres vues personnalisées pour des cas d'utilisation plus complexes. Il est donc souvent utile de comprendre comment mesurer le temps de chargement et les performances de rendu d'écran des activités et des fragments en instrumentant des traces de code personnalisées dans votre application. Vous pouvez facilement étendre cet atelier de programmation pour mesurer les performances des composants Custom View.

Ce que vous apprendrez

  • Comment ajouter Firebase Performance Monitoring à une application Android
  • Comprendre le chargement d'une Activity ou d'un Fragment
  • Comment instrumenter des traces de code personnalisées pour mesurer le temps de chargement d'une activité ou d'un fragment
  • Comprendre le rendu d'écran et ce qu'est une image lente/gelée
  • Comment instrumenter des traces de code personnalisées avec des métriques pour enregistrer des écrans lents/figés
  • Comment afficher les métriques collectées dans la console Firebase

Ce dont vous aurez besoin

  • Android Studio 4.0 ou supérieur
  • Un appareil/émulateur Android
  • Java version 8 ou supérieure

2. Mise en place

Obtenir le code

Exécutez les commandes suivantes pour cloner l'exemple de code pour cet atelier de programmation. Cela créera un dossier appelé codelab-measure-android-view-performance sur votre machine :

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

Si vous n'avez pas git sur votre machine, vous pouvez également télécharger le code directement depuis GitHub.

Importez le projet measure-view-performance-start dans Android Studio. Vous verrez probablement des erreurs de compilation ou peut-être un avertissement concernant un fichier google-services.json manquant. Nous corrigerons cela dans la section suivante de cette étape.

Dans cet atelier de programmation, nous utiliserons le plug-in Firebase Assistant pour enregistrer notre application Android auprès d'un projet Firebase et ajouter les fichiers de configuration, plug-ins et dépendances Firebase nécessaires à notre projet Android, le tout depuis Android Studio !

Connectez votre application à Firebase

  1. Accédez à Android Studio / Aide > Rechercher les mises à jour pour vous assurer que vous utilisez les dernières versions d'Android Studio et de l'assistant Firebase.
  2. Sélectionnez Outils > Firebase pour ouvrir le volet Assistant .

e791bed0999db1e0.png

  1. Choisissez Performance Monitoring à ajouter à votre application, puis cliquez sur Get started with Performance Monitoring .
  2. Cliquez sur Se connecter à Firebase pour connecter votre projet Android à Firebase (cela ouvrira la console Firebase dans votre navigateur) .
  3. Dans la console Firebase, cliquez sur Ajouter un projet , puis saisissez un nom de projet Firebase (si vous avez déjà un projet Firebase, vous pouvez sélectionner ce projet existant à la place) . Cliquez sur Continuer et acceptez les conditions pour créer le projet Firebase et une nouvelle application Firebase.
  4. Vous devriez ensuite voir une boîte de dialogue pour connecter votre nouvelle application Firebase à votre projet Android Studio.

42c498d28ead2b77.png

  1. De retour dans Android Studio, dans le volet Assistant , vous devriez voir la confirmation que votre application est connectée à Firebase.

dda8bdd9488167a0.png

Ajoutez la surveillance des performances à votre application

Dans le volet Assistant d'Android Studio, cliquez sur Ajouter la surveillance des performances à votre application .

Vous devriez voir une boîte de dialogue Accepter les modifications , après quoi Android Studio doit synchroniser votre application pour vous assurer que toutes les dépendances nécessaires ont été ajoutées.

9b58145acc4be030.png

Enfin, vous devriez voir le message de réussite dans le volet Assistant d'Android Studio indiquant que toutes les dépendances sont correctement configurées.

aa0d46fc944e0c0b.png

En tant qu'étape supplémentaire, activez la journalisation de débogage en suivant les instructions de l'étape "(Facultatif) Activer la journalisation de débogage". Les mêmes instructions sont également disponibles dans la documentation publique .

3. Exécutez l'application

Si vous avez réussi à intégrer votre application au SDK de surveillance des performances, le projet doit maintenant être compilé. Dans Android Studio, cliquez sur Exécuter > Exécuter 'app' pour créer et exécuter l'application sur votre appareil/émulateur Android connecté.

L'application dispose de deux boutons qui vous amènent à une activité et à un fragment correspondants, comme ceci :

410d8686b4f45c33.png

Dans les étapes suivantes de cet atelier de programmation, vous apprendrez à mesurer le temps de chargement et les performances de rendu d'écran de votre activité ou fragment.

4. Comprendre le chargement d'une activité ou d'un fragment

Dans cette étape, nous apprendrons ce que fait le système lors du chargement d'une activité ou d'un fragment.

Comprendre le chargement d'une activité

Pour une activité, le temps de chargement est défini comme le temps à partir du moment où l'objet d'activité est créé jusqu'à ce que la première image soit complètement dessinée à l'écran ( c'est à ce moment que votre utilisateur verra l'interface utilisateur complète de l'activité pour la première temps ). Pour mesurer si votre application est entièrement dessinée, vous pouvez utiliser la méthode reportFullyDrawn() pour mesurer le temps écoulé entre le lancement de l'application et l'affichage complet de toutes les ressources et afficher les hiérarchies.

De manière générale, lorsque votre application appelle startActivity(Intent) , le système exécute automatiquement les processus suivants. Chaque processus prend du temps, ce qui s'ajoute à la durée entre la création de l'activité et le moment où l'utilisateur voit l'interface utilisateur de l'activité sur son écran.

c20d14b151549937.png

Comprendre le chargement d'un Fragment

Semblable à l'activité, le temps de chargement d'un fragment est défini comme le temps qui commence à partir du moment où le fragment est attaché à son activité hôte jusqu'à ce que la première image de la vue du fragment soit complètement dessinée à l'écran.

5. Mesurez le temps de chargement d'une activité

Les retards dans la première image peuvent entraîner une mauvaise expérience utilisateur. Il est donc important de comprendre le retard de chargement initial subi par vos utilisateurs. Vous pouvez instrumenter une trace de code personnalisée pour mesurer ce temps de chargement :

  1. Démarrez la trace de code personnalisé (nommée TestActivity-LoadTime ) dans la classe Activity dès que l'objet Activity est créé.

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. Remplacez le rappel onCreate() et obtenez la vue ajoutée par la méthode 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. Nous avons inclus une implémentation de FistDrawListener , qui a deux rappels : onDrawingStart() et onDrawingFinish() (voir la section suivante ci-dessous pour plus de détails sur FirstDrawListener et ce qui peut affecter ses performances) . Enregistrez le FirstDrawListener à la fin du rappel onCreate() de Activity. Vous devez arrêter votre viewLoadTrace dans le rappel 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. Relancez l'application. Ensuite, filtrez le logcat avec " Logging trace metric ". Appuyez sur le bouton LOAD ACTIVITY et recherchez les journaux comme ci-dessous :
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Félicitations ! Vous avez mesuré avec succès le temps de chargement d'une activité et signalé ces données à Firebase Performance Monitoring. Nous verrons la métrique enregistrée dans la console Firebase plus tard dans cet atelier de programmation.

Objectif de FirstDrawListener

Dans la section juste au-dessus, nous avons enregistré un FirstDrawListener . Le but de FirstDrawListener est de mesurer quand la première image a commencé et terminé le dessin.

Il implémente le ViewTreeObserver.OnDrawListener et remplace le rappel onDraw() qui est invoqué lorsque l'arborescence de la vue est sur le point d'être dessinée. Il encapsule ensuite le résultat pour fournir deux rappels utilitaires onDrawingStart() et onDrawingFinish() .

Le code complet de FirstDrawListener se trouve dans le code source de cet atelier de programmation .

6. Mesurer le temps de chargement d'un Fragment

La mesure du temps de chargement d'un fragment est similaire à la façon dont nous le mesurons pour une activité, mais avec quelques différences mineures. Encore une fois, nous allons instrumenter une trace de code personnalisée :

  1. Remplacez le rappel onAttach() et commencez à enregistrer votre fragmentLoadTrace . Nous nommerons cette trace Test-Fragment-LoadTime .

Comme expliqué dans une étape précédente, l'objet Fragment peut être créé à tout moment, mais il ne devient actif que lorsqu'il est attaché à son activité hôte.

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. Enregistrez FirstDrawListener dans le rappel onViewCreated() . Ensuite, comme dans l'exemple Activity, arrêtez la trace dans 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. Relancez l'application. Ensuite, filtrez le logcat avec " Logging trace metric ". Appuyez sur le bouton LOAD FRAGMENT et recherchez les journaux comme ci-dessous :
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Félicitations ! Vous avez mesuré avec succès le temps de chargement d'un fragment et signalé ces données à Firebase Performance Monitoring. Nous verrons la métrique enregistrée dans la console Firebase plus tard dans cet atelier de programmation.

7. Comprendre le rendu d'écran et ce qu'est une image lente/gelée

Le rendu de l'interface utilisateur consiste à générer un cadre à partir de votre application et à l'afficher à l'écran. Pour s'assurer que l'interaction d'un utilisateur avec votre application est fluide, votre application doit rendre les images en moins de 16 ms pour atteindre 60 images par seconde ( pourquoi 60 ips ? ). Si votre application souffre d'un rendu lent de l'interface utilisateur, le système est obligé de sauter des images et l'utilisateur percevra un bégaiement dans votre application. Nous appelons cela jank .

De même, les images gelées sont des images d'interface utilisateur dont le rendu prend plus de 700 ms. Ce délai est un problème car votre application semble être bloquée et ne répond pas aux entrées de l'utilisateur pendant presque une seconde complète pendant le rendu de l'image.

8. Mesurer les images lentes/figées d'un fragment

La surveillance des performances de Firebase capture automatiquement les images lentes/figées pour une activité ( mais uniquement si elle est accélérée par le matériel ). Cependant, cette fonctionnalité n'est actuellement pas disponible pour les fragments. Les trames lentes/gelées d'un fragment sont définies comme les trames lentes/figées pour l'ensemble de l'activité entre les onFragmentAttached() et onFragmentDetached() dans le cycle de vie du fragment.

En nous inspirant de la classe AppStateMonitor ( qui fait partie du SDK de surveillance des performances responsable de l'enregistrement des traces d'écran pour Activity ), nous avons implémenté la classe ScreenTrace ( qui fait partie de ce dépôt de code source de codelab ). La classe ScreenTrace peut être connectée au rappel du cycle de vie de FragmentManager de l'activité pour capturer les images lentes/figées. Cette classe fournit deux API publiques :

  • recordScreenTrace() : Lance l'enregistrement d'une trace d'écran
  • sendScreenTrace() : arrête l'enregistrement d'une trace d'écran et attache des métriques personnalisées pour enregistrer le nombre total d'images, lent et gelé

En associant ces métriques personnalisées, les traces d'écran pour les fragments peuvent être gérées de la même manière que les traces d'écran pour une activité et peuvent être affichées avec d'autres traces de rendu d'écran dans le tableau de bord des performances de la console Firebase.

Voici comment enregistrer les traces d'écran pour votre fragment :

  1. Initialisez la classe ScreenTrace dans votre Activity qui héberge le Fragment.

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. Lorsque vous chargez votre fragment, enregistrez-vous pour FragmentLifecycleCallbacks et remplacez les onFragmentAttached() et onFragmentDetached() . Nous l'avons fait pour vous. Vous devez commencer à enregistrer les traces d'écran dans le rappel onFragmentAttached() et arrêter l'enregistrement dans le rappel 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. Relancez l'application. Appuyez ensuite sur le bouton LOAD FRAGMENT . Attendez quelques secondes, puis cliquez sur le back button dans la barre de navigation inférieure.

Filtrez le logcat avec " Logging trace metric ", puis recherchez les logs comme ci-dessous :

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

Filtrez le logcat avec « FireperfViews », puis recherchez les journaux comme ci-dessous :

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

🎉 Félicitations ! Vous avez mesuré avec succès les images lentes/figées pour un fragment et signalé ces données à Firebase Performance Monitoring. Nous verrons les métriques enregistrées dans la console Firebase plus tard dans cet atelier de programmation.

9. Vérifier les métriques dans la console Firebase

  1. Dans le logcat, cliquez sur l'URL de la console Firebase pour accéder à la page de détails d'une trace. ceb9d5ba51bb6e89.jpeg

Sinon, dans la console Firebase , sélectionnez le projet contenant votre application. Dans le panneau de gauche, recherchez la section Release & Monitor , puis cliquez sur Performance .

  • Dans l'onglet principal du tableau de bord , faites défiler jusqu'au tableau des traces, puis cliquez sur l'onglet Traces personnalisées . Dans ce tableau, vous verrez les traces de code personnalisées que nous avons ajoutées précédemment ainsi que certaines traces prêtes à l'emploi, telles que la trace _app_start .
  • Trouvez vos deux traces de code personnalisées, TestActivity-LoadTime et TestFragment-LoadTime . Cliquez sur la durée de l'un ou l'autre pour afficher plus de détails sur les données collectées.

a0d8455c5269a590.png

  1. La page de détail de la trace du code personnalisé affiche des informations sur la durée de la trace (c'est-à-dire le temps de chargement mesuré).

5e92a307b7410d8b.png

  1. Vous pouvez également afficher les données de performances de votre trace d'écran personnalisée.
  • Revenez à l'onglet principal du tableau de bord , faites défiler jusqu'au tableau des traces, puis cliquez sur l'onglet Rendu d'écran . Dans ce tableau, vous verrez les traces d'écran personnalisées que nous avons ajoutées précédemment ainsi que toutes les traces d'écran prêtes à l'emploi, telles que la trace MainActivity .
  • Trouvez votre trace d'écran personnalisée, MainActivity-TestFragment . Cliquez sur le nom de la trace pour afficher les données agrégées du rendu lent et des images gelées.

ee7890c7e2c28740.png

10. Félicitations

Toutes nos félicitations! Vous avez mesuré avec succès le temps de chargement et les performances de rendu d'écran d'une activité et d'un fragment en utilisant Firebase Performance Monitoring !

Ce que vous avez accompli

Et après

Firebase Performance fournit d'autres méthodes de mesure des performances de votre application que la trace personnalisée. Il mesure automatiquement le temps de démarrage de l'application, les données de performance de l'application au premier plan et de l'application en arrière-plan . Il est temps pour vous de vérifier ces métriques dans la console Firebase .

De plus, Firebase Performance offre une surveillance automatique des requêtes réseau HTTP/S . Avec cela, vous pouvez facilement instrumenter les requêtes réseau sans écrire une seule ligne de code. Pouvez-vous essayer d'envoyer des requêtes réseau depuis votre application et trouver les métriques dans la console Firebase ?

Prime

Maintenant que vous savez comment mesurer le temps de chargement et les performances de rendu d'écran de votre activité/fragment en utilisant des traces de code personnalisées, pouvez-vous explorer notre base de code open source pour voir si vous pouvez capturer ces métriques prêtes à l'emploi pour n'importe quelle activité/fragment cela fait partie de l'application ? N'hésitez pas à envoyer le PR si vous le souhaitez :-)

11. Apprentissage bonus

Comprendre ce qui se passe pendant le chargement d'une activité vous aidera à mieux comprendre les caractéristiques de performance de votre application. Dans une étape précédente, nous avons décrit à un niveau élevé ce qui se passe lors du chargement d'une activité, mais le diagramme suivant décrit chaque phase de manière beaucoup plus détaillée.

cd61c1495fad7961.png