13 votes

75 marqueurs sur Map -> fuites de mémoire -> OutOfMemoryException

J'ai un problème lorsque je dessine environ 80 marqueurs sur une carte Google. J'utilise Google Maps Android API v2.

Les icônes des marqueurs sont dynamiques (elles changent dans le temps). Après avoir ajouté un marqueur à la carte, il n'est pas possible de modifier l'icône. Je dois donc supprimer tous les marqueurs et les ajouter à nouveau.

mMap.clear();
for (int i = 0; i < teams.length(); i++) {
    team = teams.get(i);
    point = new LatLng(tema.getLatitude(), team.getLongitude());

    MarkerOptions marker = new MarkerOptions().position(point).title(name).icon(BitmapDescriptorFactory.fromResource(team.getMarkerId())));
        mMap.addMarker(marker);
}

Après avoir exécuté ce code plusieurs fois (il est actualisé une fois par minute), je reçois un message OutOfMemoryExpcetion.

Lorsque l'on utilise des marqueurs plus grands, l'exception OutOfMemoryException est levée plus rapidement. Je pense donc que le problème de mémoire est lié au bitmap de l'icône qui n'est pas recyclé correctement.

J'ai également découvert que le changement de rotation de l'appareil, de paysage à portrait et vice-versa, augmente la mémoire vive utilisée. Après un GC, la mémoire n'est pas libérée.

Quelqu'un sait-il si j'ajoute les marqueurs de manière incorrecte ou si je suis confronté à un problème dans la mise en œuvre de l'API de la carte ?

J'ai essayé de reproduire l'erreur avec l'exemple d'application Google Map. Dans l'application android-sdk/extras/google/google_play_services/samples/maps/src/com/example/mapdemo/MarkerDemoActivity.java une démonstration de marqueur peut être trouvée. Pour accélérer les tests, j'ai augmenté le nombre de marqueurs créés.

int numMarkersInRainbow = 12;

changer pour

int numMarkersInRainbow = 100;

Lancez maintenant l'application de démonstration, sélectionnez les marqueurs de démonstration et faites pivoter votre appareil de portrait à paysage et vice-versa plusieurs fois.

Le tas initial :

Heap size   Allocated  Free      %Used    #Objects
11,543 BM   9,898 MB   1,645 MB  85,75%   65.982

Le tas après quelques changements d'orientation :

Heap size   Allocated  Free      %Used    #Objects
15,652 MB   11,337 MB  4,316 MB  72,43%   76.984

Le tas après quelques autres changements d'orientation :

Heap size   Allocated  Free      %Used    #Objects
21,312 MB   16,411 MB  4,901 MB  77,00%   111.350

Le résultat final sera une erreur de mémoire (OutOfMemoryExcpetion).

Un vidage de tas montre quelques fuites possibles dans le tas : https://www.box.com/s/rsy0k22dcp267se2g1fy

La décharge complète du tas : https://www.box.com/s/6lyv2p6rlc0njqxw5zgu

Mise à jour : Il semble que ce problème soit lié à une fuite de mémoire dans Android Maps V2. Voir https://code.google.com/p/gmaps-api-issues/issues/detail?id=4766 D'après le problème, cela devrait être corrigé, mais je ne l'ai pas testé moi-même.

1voto

vkinra Points 602

Oui, vous êtes confronté à un problème classique et courant qui touche de nombreux développeurs Android : le menaçant OOM. Ce problème survient lorsque vous ne nettoyez pas complètement vos anciens objets dessinés lors d'une mise à jour ou d'une rotation. Pour résoudre ce problème, vous devriez itérer à travers vos marqueurs avant mMap.clear et les mettre à null, et éventuellement demander (vous ne pouvez pas le forcer) la collecte des ordures en appelant System.gc().

0voto

Don Cowan Points 1

Voici une approche que vous pourriez adopter comme solution de contournement à un éventuel problème d'API ... détecter une rotation de l'appareil et supprimer l'objet MarketOptions en lui attribuant la valeur null ... puis le remplir à nouveau avec vos marqueurs.

0voto

Vítor de Almeida Points 489

Lorsque j'ai des problèmes de fuites de mémoire dans mes applications, je passe par le scénario suivant

  1. Charger l'application
  2. Effectuer l'opération soupçonnée de provoquer une fuite de mémoire (de préférence plus d'une fois, afin de faciliter l'analyse par la suite).
  3. Terminer l'application (en appuyant sur retour jusqu'à ce qu'elle revienne à l'écran principal)
  4. Analyser le dumping de la mémoire

Les étapes de mon analyse sont les suivantes

  1. Ouvrir l'histogramme
  2. Rechercher le nom de mon paquet
  3. Vérifier s'il y a des références qui ne doivent pas être

S'il y a des fuites et que vous avez répété l'opération en question plusieurs fois, vous verrez apparaître plusieurs instances de fragments, d'activités, de vues, etc. Afin d'identifier le coupable de la fuite :

  1. Cliquez avec le bouton droit de la souris sur un objet fuyant -> Liste des objets -> avec référence entrante
  2. Choisissez l'une des références entrantes, faites un clic droit -> Path to GC roots -> exclude WeakReferences.
  3. Ouvrez les niveaux de la pile jusqu'à ce que vous identifiiez une référence. Si le seul chemin mène à un Finalizer, c'est que vous avez trop creusé. Si ce n'est pas concluant, essayez un autre objet qui a fui et répétez les étapes.

Désolé, ce n'est pas une science exacte, mais cela vous donnera des indices qui vous permettront d'identifier plus facilement le code défectueux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X