我正在构建一个带有图像的音乐应用程序,我正在使用Picasso来加载图像。我与Picasso一起使用的目标如下:
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);
}
}
每次更改图像时,内存消耗都会增加2-3 MB。内存使用量可能会增加到200 MB(这肯定是不可接受的)。只有2个图像视图在活动中发生变化。图像大小几乎达到1200x1200。我知道它们很大但我每次都在设置之前回收位图但是内存使用量仍然像任何东西一样增加。在该应用程序崩溃之后。它有时也会出现错误尝试使用回收的Bitmap 。也尝试了
android:largeHeap="true"
但我需要减少内存使用量。请帮忙!
答案 0 :(得分:2)
一种解决方案是尝试根据屏幕的分辨率显示图像。为此,应用程序启动后,将宽度和高度像素存储在SharedPreferences
中,然后使用它来加载缩小版图像。我建议的另一个解决方案是,如果可能的话尝试使用Fresco。它使用ashmem cache
来存储大量数据。我亲自面对Picasso
这个问题并且找不到优雅的解决方案,但在切换到Fresco
之后,所有这些OOM错误都消失了。
答案 1 :(得分:1)
当您解码第二个位图时,第一个位图不是GC',因为您制作了许多位图副本,您需要ASAP使用的可用内存以及回收。
https://developer.android.com/training/displaying-bitmaps/manage-memory.html