Il faut garder à l’esprit que si cet outil peut être très utile pour trouver des références à une fuite suspectée, il peut être assez difficile et complexe à utiliser pour trouver des fuites inconnues et nécessite un bon nombre d’analyses. Cela dit, si vous le maîtrisez – c’est un excellent outil à avoir à votre ceinture !
LeakCanary
Une autre façon de trouver des fuites de mémoire est d’utiliser Leak Canary, une bibliothèque créée par Square qui vous aide à détecter les fuites de mémoire. Elle fonctionne en utilisant une classe ObjectWatcher
qui détient des références faibles à des objets détruits dans le tas. Si la référence n’est pas effacée dans les cinq secondes suivantes et que le Garbage Collector s’est exécuté, l’objet est considéré comme conservé et enregistre cela comme une fuite de mémoire potentielle dans le logcat. Plutôt malin, hein ?
Pour commencer, il suffit d’ajouter la bibliothèque à l’intérieur de vos dépendances à votre fichier build.gradle, de synchroniser et de compiler.
Il suffit de cliquer sur la notification de « dump heap » pour enquêter sur la fuite potentielle et cette boîte de dialogue s’affiche dans l’app.
Leak Canary analyse ensuite le tas en localisant les objets retenus et trouve la trace de la fuite qui est un chemin de références à chaque objet retenu. Une fois fait, une notification s’affiche résumant le nombre d’objets retenus et de fuites.
On dirait qu’il a trouvé notre fuite ! Si nous cliquons dessus, nous verrons la trace complète de la fuite:
Il nous dit que TaskActivity fuit et les références soulignées montrent la trace, il fuit de mContext
en SingletonExample
– cela semble familier ! Maintenant nous savons comment trouver une fuite en utilisant LeakCanary. 😃
Éviter les fuites de mémoire
Alors, maintenant que nous avons trouvé notre fuite de mémoire, comment pouvons-nous les éviter à l’avenir ? Vous trouverez ci-dessous quelques-unes des causes et des modèles les plus courants.
Récepteurs de diffusion
Les récepteurs de diffusion peuvent être utilisés pour écouter les événements de diffusion à l’échelle du système ou les intentions qui indiquent des informations sur le périphérique, telles que la batterie faible, la date et les changements de connectivité – par exemple que le mode avion a été désactivé. Lorsque nous les utilisons, nous devons nous rappeler de désenregistrer les récepteurs de diffusion, sinon nous garderons inévitablement une référence à l’activité.
Comment l’éviter : Tout ce que vous devez faire est d’appeler unregister()
sur votre récepteur de diffusion en onStop()
dans votre activité.
Ce pattern se retrouve également pour les asyncTask, TimerTask et les threads qui doivent être annulés en onDestroy()
pour éviter une fuite.
Contexte vers la classe Singleton
Parfois, nous devons passer le contexte d’une activité à une classe Singleton. Un exemple de ceci serait une classe utils où nous devons accéder aux ressources, aux services ou aux fichiers internes. Cependant, passer dans le contexte signifie que nous gardons inévitablement une référence à l’activité.
Comment l’éviter : Au lieu de passer dans this
d’une activité, nous pouvons passer dans le contexte de l’application s’il est disponible (si vous voulez en savoir plus sur quand utiliser quel contexte, j’ai trouvé cet article très utile !). Une solution alternative est de s’assurer que nous définissons le contexte Singleton à null à l’intérieur de la méthode onDestroy()
de l’activité.
Références statiques
Référencer une vue ou une activité comme statique signifie que la référence à l’activité ne sera pas garbage collectée. Cela devrait simplement être évité à tout moment.
Comment l’éviter : Si, pour une raison quelconque, vous devez le faire, vous pouvez vous assurer qu’il est détruit en le mettant à null dans onDestroy().
Références de classes internes
Les classes internes provoquent souvent des fuites en détenant une référence implicite à la classe externe. Cela se produit la variable de classe est déclarée comme statique ou si la classe elle-même n’est pas déclarée comme statique. Déroutant ? Oui, mais il est facile de l’éviter si nous suivons la règle simple ci-dessous.
Comment l’éviter : Rendez la classe interne statique pour éviter de détenir une référence à la classe externe et ne créez jamais une variable statique d’une classe interne. La même chose s’applique aux classes anonymes.
C’est tout ! J’espère que vous avez appris des choses sur les fuites de mémoire et comment les éviter. Bon codage ! 😄
Voici un certain nombre d’articles et de documentations que j’ai trouvés particulièrement utiles lors de mon apprentissage des fuites de mémoire :
.