J'ai une exception OutOfMemory avec une galerie de plus de 600x800 pixels JPEG.
L'environnement
J'utilise Gallery avec des images JPG d'environ 600x800 pixels.
Étant donné que mon contenu peut être un peu plus complexe que de simples images, j'ai défini chaque vue comme étant un RelativeLayout qui englobe ImageView avec le fichier JPG.
Afin "d'accélérer" l'expérience utilisateur, j'ai un cache simple de 4 emplacements qui pré-prélève (dans un boucleur) environ 1 image à gauche et 1 image à droite de l'image affichée et les conserve dans un HashMap 4 emplacements.
La plateforme
J'utilise AVD de 256 RAM et 128 Heap Size, avec un écran de 600 x 800 . Cela se produit également sur une cible Entourage Edge, sauf qu'avec le périphérique, il est plus difficile de déboguer.
Le problème
J'ai eu une exception:
OutofMemoryError: bitmap size exceeds VM budget
Et cela se produit lors de la récupération de la cinquième image. J'ai essayé de changer la taille de mon cache d'image, et c'est toujours la même chose.
La chose étrange: il ne devrait pas y avoir de problème de mémoire
Afin de m'assurer que la limite de tas est très éloignée de ce dont j'ai besoin, j'ai défini un tableau factice de 8 Mo au début, et je ne l'ai pas référencé pour qu'il soit immédiatement envoyé. C'est un membre du fil d'activité et est défini comme suit
static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }
Le résultat est que la taille du segment de mémoire est proche de 11 Mo et que tout est gratuit .Remarque J'ai ajouté cette astuce après le début de son crash. Cela rend OutOfMemory moins fréquent.
Maintenant, j'utilise DDMS. Juste avant le crash (ne change pas beaucoup après le crash), DDMS indique:
ID Heap Size Allocated Free %Used #Objects
1 11.195 MB 2.428 MB 8.767 MB 21.69% 47,156
Et dans le tableau de détail, il montre:
Type Count Total Size Smallest Largest Median Average
free 1,536 8.739MB 16B 7.750MB 24B 5.825KB
Le bloc le plus grand mesure 7,7 Mo. Et pourtant, le LogCat dit:
ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process.
Si vous tenez compte de la relation entre la médiane et la moyenne, il est plausible de supposer que la plupart des blocs disponibles sont très petits. Cependant, il y a un bloc assez grand pour le bitmap, il est 7.7M. Comment se fait-il que cela ne soit toujours pas suffisant?
Remarque: j'ai enregistré une trace de tas. Lorsqu'on examine la quantité de données allouées, on ne sent pas que plus de 2 millions de dollars sont alloués. Cela correspond au rapport de mémoire disponible de DDMS.
Merci beaucoup
Meymann
Je pense qu'il n'y a rien de spécial dans votre cas. Il n'y a tout simplement pas assez de mémoire. Vous ne pouvez pas avoir plusieurs bitmaps 600x800 en mémoire, ils consomment trop de mémoire. Vous devez les enregistrer sur SD et les charger en mémoire à la demande. Je pense que c'est exactement ce que vous faites.
Vous devez savoir une chose: DDMS affiche la consommation de mémoire Java. Mais il y a aussi de la mémoire native qui n'est pas affichée dans DDMS. Et les images, pour autant que je sache, sont créées dans la mémoire native. DDMS est donc un mauvais outil pour suivre ces problèmes de mémoire. Vous devez simplement vous assurer que vous libérez de la mémoire, que les images sont collectées par Garbage Collector une fois que vous n'en avez plus besoin.
Garbage Collector fonctionne selon son propre calendrier. C'est pourquoi vous devriez appeler la méthode Bitmap.recycle () sur des bitmaps dont vous n'avez plus besoin. Cette méthode libère exactement la mémoire native qui vous manque. De cette façon, vous ne dépendez pas de GC et vous pourrez libérer le plus gros morceau de mémoire dès que possible.
Tout d’abord, vous devez vous assurer que vous ne perdez pas de bitmaps.
Voici un Nice post sur les allocations de mémoire, cela peut vous aider à creuser plus profondément
Vous ne savez pas si c'est une option pour vous, mais avez-vous essayé le suréchantillonnage d'images Étrange problème de mémoire insuffisante lors du chargement d'une image dans un objet Bitmap ?
La question a été posée en 2010, lorsque Froyo était frais. Tant de choses se sont passées depuis… .. Avant la version 3.0, les bitmaps étaient alloués dans JNI. La mémoire ne figurait pas dans les statistiques de Dalvik. Cela ne doit plus être monolithique . Avant la version 2.3, les statistiques de mémoire pour JNI n'étaient pas disponibles (appels de décodage bitmap JNI) dans logcat . En 2010, Nexus One était haut de gamme, avec moins de 300 Mo. Le budget pour une application était d'environ 16MB. De nos jours, il y a environ 8 fois cette mémoire.
J'ai également été confronté à un problème similaire il y a quelques semaines et je l'ai résolu en réduisant les images jusqu'à un point optimal. J'ai écrit l'approche complète dans mon blog ici et j'ai téléchargé un exemple de projet complet avec un code sujet à MOO contre un code de validation MOO ici .
Il y a eu beaucoup de temps depuis que j'ai posé cette question.
La réponse devrait être divisée en deux parties: Essayez de vous assurer que vous n'allouez pas de petits éléments que vous ne pouvez pas libérer avant d'obtenir un bitmap. Avant Ginger, la mémoire pour bmps devait être continue, et elle n’était pas comptée dans la mémoire VM. Toujours regarder le logcat. Voir une conférence sur la mémoire de Google IO 2011 . Publier Ginger c'est plus facile. Depuis Honeycomb, les bitmaps sont même comptabilisés dans votre zone Java. Il n'y a pas de zone JNI… .. Utilisez toujours recycler pour les bitmaps dont vous n'avez pas besoin. N'attendez pas le GC.