2010-06-13 8 views
19

Je rencontre un problème avec les bitmaps sur une application Android sur laquelle je travaille. Ce qui est supposé se produire, c'est que l'application télécharge des images à partir d'un site Web, les enregistre sur l'appareil, les charge dans la mémoire sous forme de bitmaps dans une liste d'arrays et les affiche à l'utilisateur. Tout fonctionne correctement lorsque l'application est démarrée. Cependant, j'ai ajouté une option de rafraîchissement pour l'utilisateur où les images sont supprimées, et le processus décrit ci-dessus commence partout.Android "Essayer d'utiliser bitmap recyclé" erreur?

Mon problème: En utilisant l'option d'actualisation, les anciennes images étaient encore en mémoire et j'obtiendrais rapidement OutOfMemoryErrors. Ainsi, si les images sont en train d'être rafraîchies, je l'ai fait parcourir à l'arrayliste et recycler les vieilles images. Toutefois, lorsque l'application va charger les nouvelles images dans l'arborescence, elle se bloque avec une erreur "Essayer d'utiliser le bitmap recyclé". Pour autant que je sache, recycler un bitmap détruit le bitmap et libère sa mémoire pour d'autres objets. Si je souhaite réutiliser le bitmap, il doit être réinitialisé. Je crois que je fais ceci quand les nouveaux dossiers sont chargés dans l'arraylist, mais quelque chose est toujours faux. Toute aide est grandement appréciée car c'est très frustrant. Le code de problème est ci-dessous. Je vous remercie!

public void fillUI(final int refresh) { 
// Recycle the images to avoid memory leaks 
if(refresh==1) { 
    for(int x=0; x<images.size(); x++) 
     images.get(x).recycle(); 
    images.clear(); 
    selImage=-1; // Reset the selected image variable 
} 
final ProgressDialog progressDialog = ProgressDialog.show(this, null, this.getString(R.string.loadingImages)); 
// Create the array with the image bitmaps in it 
new Thread(new Runnable() { 
    public void run() { 
     Looper.prepare(); 
     File[] fileList = new File("/data/data/[package name]/files/").listFiles(); 
     if(fileList!=null) { 
      for(int x=0; x<fileList.length; x++) { 
       try { 
        images.add(BitmapFactory.decodeFile("/data/data/[package name]/files/" + fileList[x].getName())); 
       } catch (OutOfMemoryError ome) { 
        Log.i(LOG_FILE, "out of memory again :("); 
       } 
      } 
      Collections.reverse(images); 
     } 
     fillUiHandler.sendEmptyMessage(0); 
    } 
}).start(); 

fillUiHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     progressDialog.dismiss(); 
    } 
}; 

}

Répondre

19

Vous n'avez pas réellement besoin d'appeler la méthode de recyclage ici. Le bouton Actualiser devrait juste effacer le tableau, garbage collector libérera la mémoire plus tard. Si vous obtenez OutOfMemory, cela signifie que d'autres objets font toujours référence à vos anciennes images et Garbage Collector ne peut pas les supprimer.

Je peux supposer que certains ImageViews affichent vos bitmaps et qu'ils gardent des références à ces bitmaps. Vous ne pouvez pas supprimer les anciens bitmaps tant qu'ils sont encore affichés. Donc, une solution possible consiste à effacer ImageVIews aussi. Après cela, vous pouvez effacer le tableau et le remplir avec de nouvelles images. Recycle libère de la mémoire, mais ImageView affiche toujours le bitmap et ne peut pas le faire après le recyclage, c'est pourquoi vous obtenez "Essayer d'utiliser le bitmap recyclé".

Ce ne sont que des suppositions car je ne peux pas voir votre code complet.

+3

Cour. "Vous n'avez pas vraiment besoin d'appeler la méthode de recyclage ici". Hm, intéressant. Jusqu'à présent, ce que j'ai lu sur le web, je pensais aussi que c'est la façon de le faire et devrait être appelé. J'ai toujours appelé ça aussi. J'ai également rencontré des problèmes de mémoire lorsque j'utilisais beaucoup de bitmaps. Un bon moyen de réduire les problèmes de mémoire est d'utiliser des caches SoftReference, comme suggéré par Romain Guy. Il l'utilise par exemple dans http://shelves.googlecode.com/svn/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java A propos de SoftReferences: http: //java.sun. com/j2se/1.5.0/docs/api/java/lang/ref/SoftReference.html –

+4

Le recyclage est bon, mais ce n'est pas nécessaire. GC nettoiera la mémoire quand même. Recycler le nettoiera plus rapidement. C'est comme ça que je le comprends. – Fedor

+1

Merci Fedor! Je me suis assuré d'annuler toutes les vues qui utilisaient les bitmaps avant d'effacer et de recréer le tableau et cela a fait l'affaire. :) – Mike

4

Si la mémoire est très grande, vous feriez mieux de recycler le bitmap vous-même. Le CPG ne peut pas être contrôlé.