LruCache内存不足?

时间:2017-02-14 16:20:14

标签: android android-lru-cache

在最后一行我遇到了崩溃:

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会终止?

1 个答案:

答案 0 :(得分:2)

  

如何避免它?

嗯,您可以使用decodeStream()代替decodeByteArray()来帮助您解决问题。就目前而言,在解码之前,通过读取整个编码图像,你毫无意义地浪费堆空间。

但是,一般情况下,您的问题与LRUCache无关,而且与尝试进行大型(~30MB)分配有关。 31961104字节,作为Bitmap,相当于2826px乘2826px图像。这比大多数Android屏幕要大得多。对于那些一个,你可能没有一个连续的堆空间块,更不用说18.对于低端Android设备,18可能占用的内存比整个设备多。

  

我理解31MB是使用内存的限制吗?

没有。该错误表示您没有足够用于该映像的单个可用内存块。

  

在我的情况下,图像大约为3MB

也许是在磁盘上。大多数图像文件格式都是压缩的(PNG,JPEG,WebP,GIF等)。您使用的堆空间量基于解压缩大小。正如njzk3所说,堆空间基于分辨率(宽x高,以像素为单位)和位深度(默认为每像素4个字节)。

  

我该怎么办?

使用较小的位图。

或者,不要将整个位图加载到内存中,而是使用可以根据用户平移和缩放手势逐步加载图像的widgets