Android中高效的显示图片 - 加载大图(setImageBitmap)

加载图片尺寸和类型针对不同的图片数据来源,BitmapFactory提供了不同的解码方法(decodeResource()、decodeFile()...),这些方法在构造图片的时候会申请相应的内存空间,所以它们经常抛出内存溢出的异常。这些方法都允许传入一个BitmapFactory.Options类型的参数来获取将要构建的图片的属性。如果将inJustDecodeBounds的值设置成true,这些方法将不会真正的创建图片,也就不会占用内存,它们的返回值将会是空。但是它们会读取图片资源的属性,我们就可以从BitmapFactory.Options中获取到图片的尺寸和类型。

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
 int imageHeight = options.outHeight;
 int imageWidth = options.outWidth;
 String imageType = options.outMimeType;

解码图片之前先检查图片的大小可以有效的避免内存溢出,除非你很确定你要加载的图片不会导致内存溢出。
加载缩小比例的图片到内存中现在图片的尺寸已经获取了,接下来就是判断是将图片全尺寸加载到内存还是加载一个缩小版。判断的标准有以下几条:
全尺寸的图片需要占用多大内存空间;
应用能够提供给这张图片的内存空间的大小;
展示这张图片的imageview或其他UI组件的大小;
设备的屏幕大小和密度。

例如,填充100x100缩略图imageview时就没有必要将1024x768的图片全尺寸的加载到内存中。这时就要设置BitmapFactory.Options中的inSampleSize属性来告诉解码器来加载一个缩小比例的图片到内存中。如果以inSampleSize=4的设置来解码这张1024x768的图片,将会得到一张256x196的图片,加载这张图片使用的内存会从3M减少到196K 。inSampleSize的值是根据缩放比例计算出来的一个2的n次幂的数。下面是计算inSampleSize常用的方法。

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {  
     // Raw height and width of image  
     final int height = options.outHeight;  
     final int width = options.outWidth;  
     int inSampleSize = 1;  

     if (height > reqHeight || width > reqWidth) {    
         final int halfHeight = height / 2;    
         final int halfWidth = width / 2;    
         // Calculate the largest inSampleSize value that is a power of 2 and keeps both    
         // height and width larger than the requested height and width.    
         while ((halfHeight / inSampleSize) >= reqHeight&& (halfWidth / inSampleSize) >= reqWidth) {      
             inSampleSize *= 2;    
         }  
     }  

     return inSampleSize;
 }

加载缩小比例图片大致有三个步骤:inJustDecodeBounds设置为true获取原始图片尺寸 --> 根据使用场景计算缩放比例inSampleSize --> inJustDecodeBounds设置为false,传递inSampleSize给解码器创建缩小比例的图片。示例代码如下:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,int reqWidth, int reqHeight) {  
     // First decode with inJustDecodeBounds=true to check dimensions  
     final BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;  
     BitmapFactory.decodeResource(res, resId, options);  

     // Calculate inSampleSize  
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  

     // Decode bitmap with inSampleSize set  
     options.inJustDecodeBounds = false;  
     return BitmapFactory.decodeResource(res, resId, options);
 }

有了上面的方法我们就可以很轻松的为大小为100x100缩略图imageview加载图片了。

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

你可能感兴趣的