在最后一行我遇到了崩溃:
InputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] buf = new byte[(int) file.length()];
int numRead = in.read(buf);
final Bitmap bitmap = BitmapFactory.decodeByteArray(buf, 0, numRead); <--- crash
如何避免它?
E/dalvikvm-heap: Out of memory on a 31961104-byte allocation.
我理解31MB是使用内存的限制吗?使用LRUCache
存储图像。我设置60MB来存储数据。太过分了吗?
public static int cacheSize = 60 * 1024 * 1024; // 4MiB
public static LruCache<String, Bitmap> images = new LruCache<String, Bitmap>(cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
在我的情况下,图像大约为3MB,至少需要18个图像存储在缓存中。手机需要存储60MB这么大的需求吗?
我试着抓住代码,为什么app会终止?
答案 0 :(得分:2)
如何避免它?
嗯,您可以使用decodeStream()
代替decodeByteArray()
来帮助您解决问题。就目前而言,在解码之前,通过读取整个编码图像,你毫无意义地浪费堆空间。
但是,一般情况下,您的问题与LRUCache
无关,而且与尝试进行大型(~30MB)分配有关。 31961104字节,作为Bitmap
,相当于2826px乘2826px图像。这比大多数Android屏幕要大得多。对于那些一个,你可能没有一个连续的堆空间块,更不用说18.对于低端Android设备,18可能占用的内存比整个设备多。
我理解31MB是使用内存的限制吗?
没有。该错误表示您没有足够用于该映像的单个可用内存块。
在我的情况下,图像大约为3MB
也许是在磁盘上。大多数图像文件格式都是压缩的(PNG,JPEG,WebP,GIF等)。您使用的堆空间量基于解压缩大小。正如njzk3所说,堆空间基于分辨率(宽x高,以像素为单位)和位深度(默认为每像素4个字节)。
我该怎么办?
使用较小的位图。
或者,不要将整个位图加载到内存中,而是使用可以根据用户平移和缩放手势逐步加载图像的widgets。