1 图片加载方式
BitmapFactory
类提供了四类方法:decodeFile、decodeResource、decodeStream和decodeByteArray,
分别用于支持从文件系统、资源、输入流以及字节数组中加载出一个Bitmap对象
其中decodeFile
和decodeResource
又间接调用了decodeStream
方法,这四类方法最终是在Android的底层实现的,对应着BitmapFactory
类的几个native方法
2 如何高效加载BitMap
如何高效地加载Bitmap呢?其实核心思想也很简单,那就是采用BitmapFactory. Options
来加载所需尺寸的图片。
这里假设通过ImageView
来显示图片,很多时候ImageView
并没有图片的原始尺寸那么大,这个时候把整个图片加载进来后再设给ImageView
,这显然是没必要的,因为ImageView并没有办法显示原始的图片。通过BitmapFactory.Options
就可以按一定的采样率来加载缩小后的图片,将缩小后的图片在ImageView
中显示,这样就会降低内存占用从而在一定程度上避免OOM
,提高了Bitmap
加载时的性能
通过BitmapFactory.Options
来缩放图片,主要是用到了它的inSampleSize
参数,即采样率。
2.1 采样率说明:
设置inSanmpleSize
为2
,则图片的宽高都会变成原来的1/2
,则像素数为原图的1/4
,其占的内存也为原图的1/4
inSampleSize
必须是大于1的整数图片才会有缩小的效果,并且采样率同时作用于宽/高,这将导致缩放后的图片大小以采样率的2次方形式递减,即缩放比例为1/(inSampleSize的2次方),比如inSampleSize为4,那么缩放比例就是1/16。有一种特殊情况,那就是当inSampleSize小于1时,其作用相当于1,即无缩放效果
2.2 采样率获取
通过采样率即可有效地加载图片,那么到底如何获取采样率呢?获取采样率也很简单,遵循如下流程:
(1)将BitmapFactory.Options的inJustDecodeBounds
参数设为true
并加载图片。
(2)从BitmapFactory.Options
中取出图片的原始宽高信息,它们对应于outWidth
和outHeight
参数。
(3)根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
。
(4)将BitmapFactory.Options
的inJustDecodeBounds
参数设为false,然后重新加载图片
这里说明一下inJustDecodeBounds
参数,当此参数设为true
时,BitmapFactory
只会解析图片的原始宽/高信息,并不会去真正地加载图片,所以这个操作是轻量级的。
这个时候BitmapFactory
获取的图片宽/高信息和图片的位置以及程序运行的设备有关,比如同一张图片放在不同的drawable
目录下或者程序运行在不同屏幕密度的设备上,这都可能导致BitmapFactory
获取到不同的结果,之所以会出现这个现象,这和Android
的资源加载机制有关。后面会单独再写一篇关于Android
图片资源加载机制的文章
2.3 采样率计算方式
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;
}