38 votes

Recycler le bitmap d'ImageView

J'ai quelque chose comme ça :

Bitmap.Config conf = Bitmap.Config.ARGB_8888;
WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, conf));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView.setImageBitmap(bm);

Et j'applique ceci sur plus de 10 imageViews qui sont créées une par une. A chaque fois que je crée une nouvelle ImageView, je veux recycler l'objet 'bm' de la première, parce que ce code là-haut, fait grossir mon tas de plus en plus et jette ensuite OutOfMemoryError alors je le fais :

bm.recycle()

juste après avoir fixé le Bitmap (bm) à l'objet imageView. Cela provoque une exception car le canevas de l'ImageView veut dessiner un bitmap recyclé.

Comment recycler un Bitmap qui a déjà été placé comme image sur ImageView ?

Mercib

56voto

devconsole Points 3027

Dans votre méthode onDestroy, vous pourriez essayer quelque chose comme ceci :

ImageView imageView = (ImageView)findViewById(R.id.my_image);
Drawable drawable = imageView.getDrawable();
if (drawable instanceof BitmapDrawable) {
    BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    Bitmap bitmap = bitmapDrawable.getBitmap();
    bitmap.recycle();
}

Le moulage devrait fonctionner puisque setImageBitmap est implémenté en tant que

public void setImageBitmap(Bitmap bm) {
    setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
}

2voto

Felix Points 33944

Si vous définissez le même objet bitmap sur toutes vos ImageView il ne devrait pas lancer un OutOfMemoryError . En principe, cela devrait fonctionner :

WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, Bitmap.Config.ARGB_8888));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView1.setImageBitmap(bm.get());
imageView2.setImageBitmap(bm.get());
imageView3.setImageBitmap(bm.get());
imageView4.setImageBitmap(bm.get());
imageView5.setImageBitmap(bm.get());
// ...

Si cela ne fonctionne pas, cela signifie simplement que votre bitmap est trop grand (6000x2000 pixels représentent environ 12 mégaoctets, si j'ai bien calculé). Vous pouvez soit :

  • réduire la taille de votre bitmap
  • réduire l'utilisation d'autres choses qui utilisent beaucoup de mémoire

1voto

La réponse de Devconsole est excellente, mais vous pouvez également stocker tous les objets bitmap dans une liste comme membre de votre classe, puis les recycler dans le cycle lorsque la méthode onDestroy() de l'activité (ou toute autre méthode de cycle de vie de libération du composant où vous utilisez le bitmap) sera appelée.

-1voto

Josh Points 4631

Ne créez pas d'images plus grandes que ce dont vous avez besoin à un moment donné. Les limitations du tas sont conçues pour vous empêcher de vous accrocher et d'occuper complètement la mémoire limitée de l'appareil.

Si vous avez besoin de plus de détails parce que vous prévoyez de faire un zoom, rendez à nouveau cette partie de l'image avec plus de détails au moment du zoom, en excluant les parties que vous ne visualisez pas.

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