Java 什么';位图的这种inSampleSize计算方法有什么问题?内存不足
在我的应用程序中,我反复浏览图像的URL,解码并将它们放入Java 什么';位图的这种inSampleSize计算方法有什么问题?内存不足,java,android,bitmap,Java,Android,Bitmap,在我的应用程序中,我反复浏览图像的URL,解码并将它们放入数组列表中 它们的大小可能差异很大,因此我使用inJustDecodeBounds=true选项进行“预解码”,以计算实际解码所需的inSampleSize值 请参阅下面我的方法,我希望它不太难理解。基本上,我的目标是一个大小类似的屏幕大小的设备 for (Element e: posts) { if (!e.id().equals("")) { //preparing decode options
数组列表中
它们的大小可能差异很大,因此我使用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);
}
}
用于计算屏幕像素的代码:
Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getSize(screenSize);
int screenPixels = screenSize.x * screenSize.y;
我用java.lang.OutOfMemoryError
浏览了大约60张图片,大约40个应用程序崩溃
据我所知,使用inJustDecodeBounds=true
没有分配内存,如果我的方法是正确的(我相信是正确的),非常大的图像在采样时会变得非常大,所以我不知道会出现什么问题
非常感谢您的建议。样本大小必须是二的幂。从文件中:
如果设置为大于1的值,则请求解码器对原始数据进行二次采样
图像,返回较小的图像以节省内存。样本量为
任一维中对应于单个像素的像素数
解码位图中的像素。例如,inSampleSize==4返回一个
图像的宽度/高度为原稿的1/4,宽度/高度为原稿的1/16
像素数。任何值无论您使用inSampleSize,您都无法轻松地在内存中保存与屏幕一样大的60个位图
假设使用全高清屏幕,您可以获得大约1920*1080*60*4个字节
这大约是500 MB的数据。
您需要以某种方式更改位图加载逻辑
作为回答,你们可以找出你们能用多少内存来计算。它因不同的设备而不同
但要尽可能提高应用程序的内存利用率。在Android上进行图像处理是出了名的困难。我建议您使用已建立的映像管理库,如:
他们文档中的一个示例:
Fresco的抽屉会为您显示占位符,直到图像加载完毕,并在图像到达时自动显示给您。当图像离开屏幕时,它会自动释放其内存
此外:
使用Fresco的应用程序甚至可以在低端设备上运行,而无需不断努力控制图像内存占用
我很确定这就是问题所在,不知道为什么我没有想到这一点。非常感谢。
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;
}