I am building a music app with images in it and I am using Picasso to load the images. The target I'm using with Picasso is the following:
Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
try {
if (artNormal != null) {
artNormal.recycle();
artNormal = null;
}
artNormal = Bitmap.createBitmap(bitmap);
TransitionDrawable td = null;
if (upNextShowing) {
Bitmap scaled = Bitmap.createScaledBitmap(artNormal, 10, 10, true);
td = new TransitionDrawable(new Drawable[]{
playerArt.getDrawable(),
new BitmapDrawable(context.getResources(), scaled)
});
// Updated Part -- Updated Part
if(scaled!=null){
scaled.recycle();
scaled = null;
}
} else {
td = new TransitionDrawable(new Drawable[]{
playerArt.getDrawable(),
new BitmapDrawable(context.getResources(), bitmap)
});
}
td.setCrossFadeEnabled(true);
playerArt.setImageDrawable(td);
td.startTransition(1000);
new GetBlurredAlbumArt(artNormal).execute();
} catch (Exception e) {
e.printStackTrace();
Log.e("LargePlayer", "Error :" + e.getLocalizedMessage());
Log.e("LargePlayer", "Error :" + e.getCause());
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.e("LargePlayer", "Picasso Load Failed");
TransitionDrawable td = null;
if (artNormal != null) {
artNormal.recycle();
artNormal = null;
}
artNormal = BitmapFactory.decodeResource(context.getResources(),
R.drawable.album_art_large);
artNormal = Bitmap.createScaledBitmap(artNormal, 800, 800, true);
if (upNextShowing) {
Bitmap scaled = Bitmap.createScaledBitmap(artNormal, 10, 10, true);
td = new TransitionDrawable(new Drawable[]{
playerArt.getDrawable(),
new BitmapDrawable(context.getResources(), scaled)
});
// Updated Part -- Updated Part
if(scaled!=null){
scaled.recycle();
scaled = null;
}
} else {
td = new TransitionDrawable(new Drawable[]{
playerArt.getDrawable(),
new BitmapDrawable(context.getResources(), BitmapFactory.decodeResource(context.getResources(),
R.drawable.album_art_large))
});
}
td.setCrossFadeEnabled(true);
playerArt.setImageDrawable(td);
td.startTransition(1000);
new GetBlurredAlbumArt(artNormal).execute();
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
class GetBlurredAlbumArt extends AsyncTask<Void, Void, Bitmap> {
Bitmap bitmap;
public GetBlurredAlbumArt(Bitmap bitmap) {
this.bitmap = bitmap;
}
@Override
protected Bitmap doInBackground(Void... params) {
bitmap = Bitmap.createScaledBitmap(bitmap, 300, 300, true);
bitmap = ImageUtilties.fastblur(bitmap, 100);
try {
return bitmap;
} catch (Exception e) {
Log.e("LargePlayer", "Error :" + e.getLocalizedMessage());
Log.e("LargePlayer", "Error :" + e.getCause());
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
TransitionDrawable td = new TransitionDrawable(new Drawable[]{
blurredColors.getDrawable() != null ? blurredColors.getDrawable() : new ColorDrawable(Color.WHITE),
new BitmapDrawable(context.getResources(), bitmap)
});
td.setCrossFadeEnabled(true);
blurredColors.setImageDrawable(td);
td.startTransition(1000);
}
}
Every time the image is changed memory consumption is increased by 2-3 MB. Memory usage could increase upto 200 MB (which is surely not acceptable). There are only 2 imageviews that change in the activity. Image sizes are nearly upto 1200x1200. I know they are pretty big but I am recycling the bitmap every time before setting but still the Memory usage increases like anything. After that application crashes. It also sometimes gives the error trying to use a recycled Bitmap. Also tried
android:largeHeap="true"
But I need to decrease memory usage. Please help!