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。

 

 


 

posted on 2019-02-19 18:11  天凉才是好个秋  阅读(705)  评论(0编辑  收藏  举报

导航