我在加载"大"时使用Picasso获得Out Of Memory异常。来自Android Gallery的图像(> 1.5MB)(使用startActivityForResult)。
我使用自定义Target对象,因为我需要在Bitmap准备就绪时对其进行预处理,并且我还使用自定义Transform对象来缩放Bitmap。
问题是我的Transform对象上的方法public Bitmap transform(Bitmap source)
从未被调用,因为Out of Memory Exception,所以我没有机会重新采样图像。
但是,如果我使用.resize(maxWidth, maxHeight)
方法,那么它会加载图像OK。我认为Transform对象也是出于这个目的,但似乎在调整大小后调用transform方法,如果我不调用resize,那么它将以Out of Memory结束。
问题是,调整大小时我需要指定宽度和高度,但我需要缩放并保持宽高比。
考虑图像将从用户图库中选择,因此它们可以更大或更小,纵向,平方或横向等,因此我需要自己的Transformation对象来执行需要我的应用程序的逻辑。
答案 0 :(得分:59)
我找到了解决方案..
在我的Transform对象中,我需要将图像(保持纵横比)缩放到1024 x 768 max。
除非我调用.resize(width, height)
对图像进行重新取样,否则永远不会调用变换对象。
为了保持宽高比并使用调整大小,我拨打.centerInside()
。这样,图像将被缩放重新采样以适合宽度,高度)。
我给.resize(宽度,高度)的值是Math.ceil(Math.sqrt(1024 * 768))
。
通过这种方式,我确保图像的自定义变换对象更高,并且还可以避免内存异常
更新:完整示例
按照这个例子,你会得到一个适合MAX_WIDTH和MAX_HEIGHT界限的图像(保持纵横比)
private static final int MAX_WIDTH = 1024;
private static final int MAX_HEIGHT = 768;
int size = (int) Math.ceil(Math.sqrt(MAX_WIDTH * MAX_HEIGHT));
// Loads given image
Picasso.with(imageView.getContext())
.load(imagePath)
.transform(new BitmapTransform(MAX_WIDTH, MAX_HEIGHT))
.skipMemoryCache()
.resize(size, size)
.centerInside()
.into(imageView);
这是我的自定义BitmapTransform类:
import android.graphics.Bitmap;
import com.squareup.picasso.Transformation;
/**
* Transformate the loaded image to avoid OutOfMemoryException
*/
public class BitmapTransform implements Transformation {
private final int maxWidth;
private final int maxHeight;
public BitmapTransform(int maxWidth, int maxHeight) {
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
}
@Override
public Bitmap transform(Bitmap source) {
int targetWidth, targetHeight;
double aspectRatio;
if (source.getWidth() > source.getHeight()) {
targetWidth = maxWidth;
aspectRatio = (double) source.getHeight() / (double) source.getWidth();
targetHeight = (int) (targetWidth * aspectRatio);
} else {
targetHeight = maxHeight;
aspectRatio = (double) source.getWidth() / (double) source.getHeight();
targetWidth = (int) (targetHeight * aspectRatio);
}
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
source.recycle();
}
return result;
}
@Override
public String key() {
return maxWidth + "x" + maxHeight;
}
}
答案 1 :(得分:2)
在Android开发者网站上有一篇非常好的文章,当我在加载大图片时遇到同样的问题时,它帮了我很多。
This文章解释了导致错误的原因以及如何解决错误。还有其他文章(参见菜单),例如,缓存图像。