高效的显示位图(二):高效加载大…

来源:互联网 发布:安庆历史气象数据查询 编辑:程序博客网 时间:2024/05/21 09:44
- 图像经常比应用UI需要的大
- 理想的,值加载低分辨率版本到内存中
- 低分辨率版本应当与显示它的界面元素匹配
- 本篇讲解如何不超过应用内存限制解码大图片,途径是加载更小的二次采样版本

-----------------------------------------------------------------------------------------
读取位图尺寸和类型

- BitmapFactory类提供了多个解码方法来从不同的源创建位图对象
- 容易OOM
- BitmapFactory.Options:
  * 指定解码选项
  *inJustDecodeBound:只取尺寸、类型信息,不分配内存给图像数据
  * 这项技术允许你读取尺寸和类型,而免于真正的构建位图:
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;
- 为了避免OOM,要在解码位图之前检查尺寸,除非你确信没有问题


-----------------------------------------------------------------------------------------
加载缩小版本到内存

- 已经获取的尺寸信息可以用来决定是加载原始图像还是加载二次采样的图像
- 应当考虑:
  • 估计加载原始图像的内存使用情况
  • 你希望用于图像加载的内存数量
  • 目标ImageView或UI组件的尺寸
  • 屏幕的尺寸和密度
-为告知解码器进行二次采样,在BitmapFactory.Options中将inSampleSize(倍数)设置为true
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) {

       
// Calculate ratios of height and width to requested height and width
       
final int heightRatio = Math.round((float) height / (float) reqHeight);
       
final int widthRatio = Math.round((float) width / (float) reqWidth);

       
// Choose the smallest ratio as inSampleSize value, this will guarantee
       
// a final image with both dimensions larger than or equal to the
       
// requested height and width.
        inSampleSize
= heightRatio < widthRatio ? heightRatio : widthRatio;
   
}

   
return inSampleSize;
}
- inSampleSize设为2能让解码器更快更有效。但如果二次采样的图像用于缓存,用最合适的倍率仍然是值得的
- inJustDecodeBounds设置回false
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);
}
- 此方法很容易的将大尺寸图像变成100*100版本加载到ImageView:
mImageView.setImageBitmap(
    decodeSampledBitmapFromResource
(getResources(), R.id.myimage, 100, 100));