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 devons-nous 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 complètement 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.

Firebase Performance Monitoring ne fournit-il 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ébut 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 les images lentes et figées pour les activités, mais pas pour les activités). Fragments). Cependant, les applications industrielles 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 de vue personnalisée.

Ce que vous apprendrez

  • Comment ajouter Firebase Performance Monitoring à une application Android
  • Comprendre le chargement d'une activité 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/gelé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

Obtenez 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 ordinateur :

$ 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 plugin Firebase Assistant pour enregistrer notre application Android auprès d'un projet Firebase et ajouter les fichiers de configuration, plugins 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 Firebase Assistant.
  2. Sélectionnez Outils > Firebase pour ouvrir le volet Assistant .

e791bed0999db1e0.png

  1. Choisissez Performance Monitoring à ajouter à votre application, puis cliquez sur Démarrer avec Performance Monitoring .
  2. Cliquez sur 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 une surveillance des performances à votre application .

Vous devriez voir une boîte de dialogue pour accepter les modifications, après quoi Android Studio doit synchroniser votre application pour garantir 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

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

3. Exécutez l'application

Si vous avez intégré avec succès votre application au SDK Performance Monitoring, le projet doit maintenant être compilé. Dans Android Studio, cliquez sur Exécuter > Exécuter « application » 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 allant de la création de l'objet d'activité jusqu'à ce que la première image soit complètement dessinée à l'écran ( c'est à ce moment-là que votre utilisateur verra l'interface utilisateur complète de l'activité pour la première fois). 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.

À un niveau élevé, 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 commençant à 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. Mesurer le temps de chargement d'une activité

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

  1. Démarrez la trace du 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 comporte 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 l'activité. 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. Réexécutez 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 réussi à mesurer le temps de chargement d'une activité et à signaler 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 le moment où la première image a commencé et terminé le dessin.

Il implémente ViewTreeObserver.OnDrawListener et remplace le rappel onDraw() qui est invoqué lorsque l'arborescence View est sur le point d'être dessinée. Il encapsule ensuite le résultat pour fournir deux rappels d'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 le 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. Réexécutez 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 réussi à mesurer le temps de chargement d'un fragment et à signaler 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 garantir la fluidité de l'interaction d'un utilisateur avec votre application, votre application doit restituer 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 du jank .

De même, les images figé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 bloquée et ne répond pas aux entrées de l'utilisateur pendant près d'une seconde complète pendant le rendu de l'image.

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

Firebase Performance Monitoring capture automatiquement les images lentes/gelé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 images lentes/gelées d'un fragment sont définies comme les images lentes/gelées pour l'ensemble de l'activité entre les rappels onFragmentAttached() et onFragmentDetached() dans le cycle de vie du fragment.

En nous inspirant de la classe AppStateMonitor ( qui fait partie du SDK Performance Monitoring 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 l'atelier de programmation ). La classe ScreenTrace peut être connectée au rappel du cycle de vie du FragmentManager de l'activité pour capturer les images lentes/gelées. Cette classe fournit deux API publiques :

  • recordScreenTrace() : démarre 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 d'images totales, lentes et gelées

En attachant 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 Performances de la console Firebase.

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

  1. Initialisez la classe ScreenTrace dans votre activité 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, inscrivez-vous à FragmentLifecycleCallbacks et remplacez les rappels 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. Réexécutez l'application. Ensuite, appuyez 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 journaux 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/gelé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érifiez les métriques dans la console Firebase

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

Vous pouvez également, dans la console Firebase , sélectionner le projet contenant votre application. Dans le panneau de gauche, recherchez la section Release & Monitor , puis cliquez sur Performances .

  • 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é que nous avons ajoutées précédemment ainsi que certaines traces prêtes à l'emploi , telles que la trace _app_start .
  • Recherchez 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étails de la trace du code personnalisé vous montre 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 .
  • Recherchez 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 figé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 à l'aide de Firebase Performance Monitoring !

Ce que tu as accompli

Et après

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

De plus, Firebase Performance propose 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 à l'aide de 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. ça fait partie de l'application ? N'hésitez pas à envoyer le PR si vous le souhaitez :-)

11. Apprentissage bonus

Comprendre ce qui se passe lors du chargement d'une activité vous aidera à mieux comprendre les caractéristiques de performances de votre application. Dans une étape précédente, nous avons décrit en détail 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