安卓BitmapFactory.decodeStream报java.lang.OutOfMemoryError内存溢出

一丶java.lang.OutOfMemoryError异常常见原因:

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;

二丶BitmapFactory.decodeStream出现OutOfMemoryError异常

  log:java.lang.OutOfMemoryError: Failed to allocate a 4308492 byte allocation with 467872 free bytes and 456KB until OOM

  我以为是我的Bitmap太大了,于是对Bitmap进行一系列优化,点击run,然并卵又TMD出现OutOfMemoryError,还是太年轻啊。

三、解决方法

1.什么是内存泄露?
  内存泄露指程序中没有正确的释放用完的内存空间,导致运行异常或错误
2.AndroidStudio如何检测内容泄漏
  Tools——Android——Android device monitor


image.png

image.png

image.png

  通过AndroidStudio的内存检测工具很清楚的看到内存使用情况,经测试一个几百k的图片,使用BitmapFactory.decodeStream()方法却要试图分配1M的内存
  首先我们知道安卓开发中一般从网络获取图像,使用BitmapFactory的decodeStream函数来获取到bitmap。Android又在图像方面面消耗内存较多,本文就主要记录怎样正确的展现图像减少对内存的开销,有效的避免oom现象。那我们的内存为什么会被消耗那么多呢?是因为BitmapFactory的每个decode函数都会生成一个bitmap对象,内存就是去bitmap里了,如果图像过多就会出现OutOfMemoryError异常。不多说,直接上代码,以下为优化方法:

  InputStream bitmapIs = HttpUtils.getStreamFromURL(imageURL);
                Bitmap bitmap = null;
                try {
                     bitmap =getFitSampleBitmap(bitmapIs);
                } catch (Exception e) {
                    e.printStackTrace();
                }
public  static  Bitmap  getFitSampleBitmap(InputStream  inputStream) throws Exception{
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            byte[] bytes = readStream(inputStream);
            BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
            options.inSampleSize = 2;
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
    /**
     * 从inputStream中获取字节流 数组大小
     **/
        public static byte[] readStream(InputStream inStream) throws Exception{
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
            }
            outStream.close();
            inStream.close();
            return outStream.toByteArray();
        }

  BitmapFactory提供了BitmapFactory.Option,用于设置图像相关的参数, inJustDecodeBounds :如果设置为true则表示decode函数不会生成bitmap对象,仅是将图像相关的参数填充到option对象里,这样我们就可以在不生成bitmap而获取到图像的相关参数了。
  inSampleSize:表示对图像像素的缩放比例。假设值为2,表示decode后的图像的像素为原图像的1/2。
  在设置了option的inSampleSize后我们将inJustDecodeBounds设置为false再次调用decode函数时就能生成bitmap了。
最后为了保险起见加上如下代码:

if (bitmap.isRecycled()== false ){
    bitmap.recycle();
}

如果代码已经不再需要使用Bitmap对象了,手动回收。

你可能感兴趣的:(安卓BitmapFactory.decodeStream报java.lang.OutOfMemoryError内存溢出)