美文网首页Android开发经验谈程序员
安卓BitmapFactory.decodeStream报jav

安卓BitmapFactory.decodeStream报jav

作者: 小六六丶 | 来源:发表于2017-12-13 20:35 被阅读0次

    一丶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报jav

        本文链接:https://www.haomeiwen.com/subject/jqczixtx.html