zoukankan      html  css  js  c++  java
  • Android大尺寸图片加载,有效避免OOM

    图片来源:

    1.从网络加载

    2.从文件读取

    3.从资源文件加载

    这三种情况我们一般使用BitmapFactory的decodeStream,decodeFile,decodeResource来获取Bitmap,最终使用ImageView的setImageBitmap函数来显示。

    OOM原因:

    BitmapFactory的每个decode函数都会生成一个bitmap对象,用于存放解码后的图像,如果图像数据较大就会造成bitmap对象申请的内存较多,如果图像过多就会造成内存不够用自然就会出现out of memory的现象。

    处理图片加载的方法,以BitmapFactory.decodeFile为例。

     1 public static Bitmap getFitSampleBitmap(String file_path, int width, int height) {
     2     BitmapFactory.Options options = new BitmapFactory.Options();
     3     options.inJustDecodeBounds = true;
     4     BitmapFactory.decodeFile(file_path, options);
     5     options.inSampleSize = getFitInSampleSize(width, height, options);
     6     options.inJustDecodeBounds = false;
     7     return BitmapFactory.decodeFile(file_path, options);
     8 }
     9 public static int getFitInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options) {
    10     int inSampleSize = 1;
    11     if (options.outWidth > reqWidth || options.outHeight > reqHeight) {
    12         int widthRatio = Math.round((float) options.outWidth / (float) reqWidth);
    13         int heightRatio = Math.round((float) options.outHeight / (float) reqHeight);
    14         inSampleSize = Math.min(widthRatio, heightRatio);
    15     }
    16     return inSampleSize;
    17 }

     BitmapFactory提供了BitmapFactory.Option,用于设置图像相关的参数,主要介绍option里的两个成员:inJustDecodeBounds(Boolean类型) 和inSampleSize(int类型)。

    inJustDecodeBounds :如果设置为true则表示decode函数不会生成bitmap对象,仅是将图像相关的参数填充到option对象里,这样我们就可以在不生成bitmap而获取到图像的相关参数了。

    inSampleSize:表示对图像像素的缩放比例。假设值为2,表示decode后的图像的像素为原图像的1/2。在上面的代码里我们封装了个简单的getFitInSampleSize函(将传入的option.outWidth和option.outHeight与控件的width和height对应相除再取其中较小的值)来获取一个适当的inSampleSize。

    在设置了option的inSampleSize后我们将inJustDecodeBounds设置为false再次调用decode函数时就能生成bitmap了。

     1 public class BitmapUtils {
     2 
     3     //decodeFile
     4     public static Bitmap getFitSampleBitmap(String file_path, int width, int height) {
     5         BitmapFactory.Options options = new BitmapFactory.Options();
     6         options.inJustDecodeBounds = true;
     7         BitmapFactory.decodeFile(file_path, options);
     8         options.inSampleSize = getFitInSampleSize(width, height, options);
     9         options.inJustDecodeBounds = false;
    10         return BitmapFactory.decodeFile(file_path, options);
    11     }
    12 
    13     //decodeResource
    14     public static Bitmap getFitSampleBitmap(Resources resources, int resId, int width, int height) {
    15         BitmapFactory.Options options = new BitmapFactory.Options();
    16         options.inJustDecodeBounds = true;
    17         BitmapFactory.decodeResource(resources, resId, options);
    18         options.inSampleSize = getFitInSampleSize(width, height, options);
    19         options.inJustDecodeBounds = false;
    20         return BitmapFactory.decodeResource(resources, resId, options);
    21     }
    22 
    23     //decodeStream
    24     public static Bitmap getFitSampleBitmap(InputStream inputStream, int width, int height) throws Exception {
    25         BitmapFactory.Options options = new BitmapFactory.Options();
    26         options.inJustDecodeBounds = true;
    27         byte[] bytes = readStream(inputStream);
    28         //BitmapFactory.decodeStream(inputStream, null, options);
    29         BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    30         options.inSampleSize = getFitInSampleSize(width, height, options);
    31         options.inJustDecodeBounds = false;
    32 //        return BitmapFactory.decodeStream(inputStream, null, options);
    33         return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    34     }
    35 
    36     /*
    37      * 从inputStream中获取字节流 数组大小
    38     * */
    39     public static byte[] readStream(InputStream inStream) throws Exception {
    40         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    41         byte[] buffer = new byte[1024];
    42         int len = 0;
    43         while ((len = inStream.read(buffer)) != -1) {
    44             outStream.write(buffer, 0, len);
    45         }
    46         outStream.close();
    47         inStream.close();
    48         return outStream.toByteArray();
    49     }
    50     public static int getFitInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options) {
    51         int inSampleSize = 1;
    52         if (options.outWidth > reqWidth || options.outHeight > reqHeight) {
    53             int widthRatio = Math.round((float) options.outWidth / (float) reqWidth);
    54             int heightRatio = Math.round((float) options.outHeight / (float) reqHeight);
    55             inSampleSize = Math.min(widthRatio, heightRatio);
    56         }
    57         return inSampleSize;
    58     }
    59 }

    在处理stream的时候我们并不是同之前一样通过调用两次decodeStream函数来进行设置的,而是将stream转化成byte[],然后在两次调用decodeByteArray。其原因是:如果我们两次调用按照两次调用decodeStream的方式,会发现我们得到到bitmap为null。

    
    
    
  • 相关阅读:
    代理类和装饰类的区别
    spring mvc 处理映射的几种方式
    如何深入浅出的理解跳转方式:重定向和请求转发
    springMVC拦截配置
    ※版本管理※=>☆SVN工具=>※解决地域麻烦※№→搭建自己的网络SVN (SourceForge 免费) [转]
    权力社会? 金钱社会? 透过现象看本质-让权力和金钱的力量沿着制度的河道流淌,才是社会稳定的基石
    自己封装的CMusic类 【转】
    VC++中MCI播放音频文件 【转】
    DevExpress.XtraGrid 【转】
    C# Process.Start()方法详解 [转]
  • 原文地址:https://www.cnblogs.com/evolutionoflicorice/p/10402754.html
Copyright © 2011-2022 走看看