问题

在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数据生成图片      }  

更多相关文章

  1. Android图片压缩浅谈
  2. android扫描sdcard中的音视频及图片等文件
  3. android的消息处理惩罚机制(图+源码解析)——Looper,Handler,Message
  4. Android(安卓)Activity全面解析
  5. Android单点触控技术,对图片进行平移,缩放,旋转操作
  6. (六)android recovery 升级UI显示之资源文件
  7. XML解析和生成之--pull(android内置)
  8. FontAwesome-用TextView显示图片
  9. .9图片的制作(draw9patch.bat工具的使用)

随机推荐

  1. android onResume is called before you
  2. android xml解析 XmlPullParser的使用
  3. (Android)Activity的生命的周期
  4. Android Goldfish详解之一
  5. Android截屏截图方法所有方法汇总(包括Act
  6. Android 自定义权限 ( )
  7. android LocationManager的使用
  8. Sqlite3常用简单指令
  9. Android Tasks、ActivityStack和Activity
  10. Kotlin 中Butterknife 和Android 中使用b