Android加载大图防止OOM

问题

在Android的开发过程中经常遇到多张大图片的加载,图片的类型是多种多样,不同大小。但是大多数的图片都是高分辨率,总体来说,远远大于我们要展示的容器ImageView。而加载过大图片就会导致OOM异常。下面就介绍解决该问题的途径

解决途径

Android图片Bitmap对象是用BitmapFactory工具类中多种解析方法创建的。创建的方式大概分为:、
1)SD卡文件中加载解析方式

public static Bitmap decodeFile(String pathName, Options opts) {
}

2)资源中文件加载解析方式

 public static Bitmap decodeResource(Resources res, int id, Options opts) {
}

3)字节数组解析方式

 public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
}

4)网络中加载流的解析方式

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
}

这些方法会尝试为已经构建的bitmap分配内存,这时就会很容易导致OOM出现。为此每一种解析方法都提供了一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。

 /** 
     * 从SD卡中获取图片并且比例压缩 
     * @param path 路径 
     * @param mHeight 自定义高度 
     * @param mWidth 自定义宽度 
     * @return 
     */  
    public static Bitmap getBitmapFromSDCard(String path, int mHeight, int mWidth)  
    {  
        BitmapFactory.Options options = new BitmapFactory.Options();  
        options.inJustDecodeBounds = true;  
        BitmapFactory.decodeFile(path, options);  
            //计算比例值  
        options.inSampleSize = calculateInSampleSize(options,mHeight,mWidth);  
        options.inJustDecodeBounds = false;  
        return BitmapFactory.decodeFile(path, options);  
    }  

    /** 
     * 计算压缩比例值inSampleSize 
     * @param options 压缩的参数设置 
     * @param mHeight 想要的高度 
     * @param mWidth 想要的宽度 
     * @return 
     */  
    public static int calculateInSampleSize(BitmapFactory.Options options, int mHeight, int mWidth)  
    {  
        //原尺寸大小  
        int yHeight = options.outHeight;  
        int yWidth = options.outWidth;  

        int inSampleSize = 1;  
        //如果宽度大的话根据宽度固定大小缩放  
        if (yWidth > yHeight && yWidth > mWidth) {  
            inSampleSize = (int) (yWidth / mWidth);  
        }  
        //如果高度高的话根据宽度固定大小缩放  
        else if (yWidth < yHeight && yHeight > mHeight)  
        {  
            inSampleSize = (int) (yHeight / mHeight);  
        }  
        if (inSampleSize <= 0)  
            inSampleSize = 1;  
        return inSampleSize;  
    }  

观察代码,可以看出,先后解析了两次图片,首先options.inJustDecodeBounds = true以后,BitmapFactory解析一次图片,将图片的得到的option传入到方法calculateInSampleSize方法中,在方法中可以根据ImageView控件的长宽对图片进行压缩,计算出合适的inSamplesize值,最后options.inJustDecodeBounds 设置 false以后,在对图片解析一次,这时的图片的比例值inSamplesize正是我们计算出来的值。

上面的这样做已经可以图片的比例压缩,至于有需要对图片质量压缩的可以参照一下代码。

   /** 
     * 图片质量压缩(质量参数) 
     * @param image 
     * @param quality 质量参数 百分之多少 例如:0.6  0.7 
     * @return 
     */  
    public static Bitmap compressImage(Bitmap image, float quality)  
    {  
        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        image.compress(Bitmap.CompressFormat.JPEG, (int)quality*100, baos);  
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中  
        return BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片  
    }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值