在我的应用中,我正在迭代图像的网址,解码并将它们放入ArrayList<Bitmap>
。
它们的大小可能差异很大,因此我使用inJustDecodeBounds = true
选项进行“预解码”,以计算实际解码所需的inSampleSize
值。
请参阅下面的方法,我希望它不难理解。基本上我的目标是大小与设备的屏幕尺寸相似。
for (Element e: posts) {
if (!e.id().equals("")) {
//preparing decode
options = new BitmapFactory.Options();
input = new URL(e.url).openStream();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(input, null, options);
input.close();
//setting inSampleSize if necessary
int picPixels = options.outWidth * options.outHeight;
int picScreenRatio = picPixels / screenPixels;
if (picScreenRatio > 1) {
int sampleSize = picScreenRatio % 2 == 0 ? picScreenRatio : picScreenRatio + 1;
options.inSampleSize = sampleSize;
}
//actual decode
input = new URL(e.url).openStream();
options.inJustDecodeBounds = false;
Bitmap pic = BitmapFactory.decodeStream(input, null, options);
input.close();
picList.add(pic);
}
}
计算screenPixels
的代码:
Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getSize(screenSize);
int screenPixels = screenSize.x * screenSize.y;
我正在浏览大约60张图片,大约40张我的应用程序崩溃java.lang.OutOfMemoryError
。
据我了解,inJustDecodeBounds = true
没有分配内存,如果我的方法是正确的(我相信它是),非常大的图像变得非常大inSampleSize
s,所以我不知道可能是什么问题。
非常感谢任何建议。
答案 0 :(得分:2)
样本大小必须是2的幂。来自文档:
如果设置为值&gt; 1,请求解码器对原始进行二次采样 图像,返回较小的图像以节省内存。样本量是 任一维度中对应于单个像素的像素数 解码后的位图中的像素。例如,inSampleSize == 4返回一个 图像是原稿宽度/高度的1/4,和1/16 像素数。任何值&lt; = 1都被视为1.注意: 解码器使用基于2的幂的最终值,任何其他值都将 向下舍入到最接近2的幂。
这是Android - Volley库中关于如何为位图找到最佳样本大小的好方法:
int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
double wr = (double) actualWidth / desiredWidth;
double hr = (double) actualHeight / desiredHeight;
double ratio = Math.min(wr, hr);
float n = 1.0f;
while ((n * 2) <= ratio) {
n *= 2;
}
return (int) n;
}
答案 1 :(得分:2)
无论您使用inSampleSize,都无法轻松保存与内存中屏幕一样大的60位图。
假设有一个全高清屏幕,你会得到1920*1080*60*4
个字节。
大概 500 MB的数据。 您需要以某种方式更改位图加载逻辑。
在this回答中,您可以了解可以计算多少内存。它因各种设备而异。
但总是尽量让你的应用程序尽可能保持内存效率。
答案 2 :(得分:0)
在Android上正确处理图像处理是非常困难的。我建议您使用已建立的图像管理库,如Facebook's Fresco:
https://github.com/facebook/fresco
他们的文档中的一个例子:
Fresco的Drawees为您显示占位符,直到图像加载并在图像到达时自动显示。当图像离开屏幕时,它会自动释放内存。
此外:
使用Fresco的应用程序甚至可以在低端设备上运行,而无需经常努力控制图像内存占用。