web-dev-qa-db-fra.com

Recyclez 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 cela sur plus de 10 images qui sont créées une par une. Chaque fois que je crée une nouvelle ImageView, je veux recycler l'objet 'bm' du premier, provoquer ce code là-haut, faire grossir mon tas de plus en plus puis lancer OutOfMemoryError, donc je fais:

bm.recycle()

juste après avoir défini le bitmap (bm) sur l'objet imageView. Cela provoque l'exception que le canevas de l'ImageView souhaite dessiner un bitmap recyclé.

Comment recycler un bitmap qui a déjà été mis en image sur ImageView?

Thanksb

38
Peter Olsbourg

Dans votre méthode onDestroy, vous pouvez 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 cast devrait fonctionner puisque setImageBitmap est implémenté comme

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

Si vous définissez le même objet bitmap sur tous vos ImageViews, il ne devrait pas lancer un OutOfMemoryError. Fondamentalement, 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 est d'environ 12 mégaoctets, si j'ai bien calculé). Vous pouvez soit:

  • rendre votre bitmap plus petit
  • réduire les autres choses qui utilisent beaucoup de mémoire
2
Felix

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

1
Vladimir Ryhlitskiy