Analytics fait partie intégrante d'une application mobile moderne. Analytics vous permet de collecter des informations sur l'utilisateur afin de développer et d'améliorer le produit.
Souvent, la collecte d'informations réduit les performances des applications. Le processus charge en outre le CPU et la mémoire, et c'est un prix élevé. Un fonctionnement lent de l'application peut entraîner des avis négatifs des utilisateurs, abaisser la note et entraîner une perte d'audience.
Notre équipe de développeurs Android a rencontré ce problème lors du travail sur le prochain projet, qui était lié à l'actualité. Nous avons dû enregistrer l'affichage de chaque nouvelle dans la liste.
Tentative numéro 1
Ayant reçu la tâche de collecter des analyses, l'équipe a rapidement montré le résultat. Le déclencheur pour générer un événement était la méthode
onViewAttachedToWindow . Tout semble bien se passer, mais avec un défilement rapide, l'interface s'est sensiblement bloquée - quelque chose s'est mal passé. Le problème devait être résolu.
Tout le monde perçoit la suspension différemment, nous avions donc besoin de faits et de preuves. Pour mesurer le décalage, FPS (Frames Per Second) a été choisi, et FPS-mètre
TinyDenser pour mesurer le
décalage . Après avoir connecté l'utilitaire, l'équipe a reçu une confirmation objective du problème - l'indicateur est tombé, parfois de manière assez notable: moins de 30 images par seconde, l'enregistrement d'écran avec l'utilitaire activé est illustré à la figure 1.
Figure 1. Enregistrement d'écran avant optimisationTentative numéro 2
Et si vous retardez l'envoi d'événements jusqu'à ce que l'utilisateur fasse défiler la liste? Hmmm, l'équipe réfléchit et décida de créer une file d'attente d'événements et de les envoyer après l'arrêt du défilement. Tout est simple ici: nous ajoutons
OnScrollListener à
RecyclerView et attendons que le
newState soit à plat
SCROLL_STATE_IDLE - le problème est partiellement résolu.
class IdleStateScrollListener(private val analyticsFacade: AnalyticsFacade) : RecyclerView.OnScrollListener() { fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { analyticsFacade.setPending(newState != RecyclerView.SCROLL_STATE_IDLE) } }
L'étape suivante consiste à mettre en œuvre l'accumulation d'événements et leur diffusion.
Pour gérer la file d'attente, nous avons créé une classe chargée d'ajouter des événements à la file d'attente et d'envoyer des analyses au service. Pour l'envoi périodique, nous avons choisi un
ScheduledExecutorService avec un thread qui
exécutait Runnable toutes les secondes, l'heure a été sélectionnée empiriquement.
Cela a immédiatement donné des résultats, une augmentation significative du FPS. En principe, le problème a été résolu, sur la figure 2, nous voyons le résultat de l'application après la deuxième tentative. Mais il n'y avait qu'une seule tâche - des événements ont été envoyés au service, ce qui a conduit à la génération fréquente d'objets de la classe
Intent , ce qui a en outre surchargé le
GC et livré des «choses agréables» sous la forme de pauses d'
arrêt du monde .
Figure 2. Enregistrement d'écran après la deuxième tentativeTentative numéro 3
«L'envoi non d'un événement à la fois, mais d'une liste d'événements est une autre merveilleuse idée», a pensé l'équipe. Après un bref raffinement de la classe, l'équipe a implémenté la répartition des événements par la liste et a reçu des valeurs stables de l'indicateur au niveau de 55 à 60 images par seconde (figure 3).
Figure 3. Enregistrement d'écran après la troisième tentativeConclusions
La tâche triviale de collecte d'analyses s'est transformée en un processus intéressant et informatif, au cours duquel l'équipe a mis à profit ses compétences pour rechercher des problèmes de performances des applications et trouver des moyens de les résoudre. J'espère que notre expérience sera utile aux débutants comme aux développeurs expérimentés.
Pourrait-on faire autre chose?
Notre équipe a opté pour la troisième option, mais ce n'est pas la seule chose qui pourrait être appliquée.
Dans l'implémentation actuelle, lorsque la méthode
onViewAttachedToWindow est déclenchée, les
actualités sont transformées en un objet d'événement analytique et, par conséquent, un nouvel objet est créé. Une des solutions possibles est de reporter la conversion jusqu'au moment de l'envoi: accumuler dans la file d'attente non pas les événements, mais les éléments de la liste eux-mêmes. Ensuite, la conversion se produit lorsque le défilement est en mode
SCROLL_STATE_IDLE . Vous pouvez également créer un pool d'objets pour les événements. Ensemble, ces actions peuvent donner une augmentation supplémentaire des performances des applications.