契子:
在我们在了解二次采样之前,我们要了解一些图片的规格。在我们日常开发app的,大部分的时候都需要展示图片信息,图片最终对应Android中的是Bitmap(位图)对象。而Bitmap的规格的话大致上有4种:
- ALPHA_8:
- ARGB_4444:
- ARGB_8888:
- RGB_565:
但是对于APP端来说的Bitmap是一个比较麻烦的问题,主要体现在Bitmap是非常占用内存的对象,处理不当会导致APP运行卡顿甚至会出现OOM,博主上次遇到的问题是使用XRecycleview进行上拉和下拉的使用的时候,图片加载的过多导致的滑动卡顿,所以这个时候,就要用到图片优化 !
为什么要使用二次采样?
可能上面说的不够详细,现在我在详细的讲讲使用的原因:
当我们在展示一张100M大的图片,我们通常会用一个图片控件给显示出来,那么你的100M
大的图片能显示出来吗?可能就会报OOM异常,这就涉及到了图片加载时内存溢出的问题,这个时候就要用到二次采样。
总而言之:二次采样就避免加载图片时的OOM异常。
PS:OOM(OutOfMemoryError)内存溢出异常。
二次采样的目的与操作?
第一次采样:
第一次采样主要是获取图片,设置成我们需要的大小。
//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点
options.inJustDecodeBounds = true;
当我们把图片加载进来的时候,先获取图片的宽和高,这个加载不会耗费很多内存,结合我们在定义的控件的宽高,计算出我们需要缩放的比例。事实上我们在手机上显示一个分辨率特别大的图片和一个分辨率小的图片,只要不是太小,不会有很大的影响。
第二次采样:
在前一次的基础上,进行第二次采样。在我们已经成功计算出了的缩放比例,
先设置
options.inJustDecodeBounds = false;
二次采样需要将图片加载出来,首先将第一次采样的结果为参数传递给BitmapFactory,设置缩放比例,这样就不会加载整个图片进来了,而只是加载一张缩略图进来,这样不仅提高的加载速度,也节约了内存,在用户体验上,也不会有过多的差异感。
代码展示:
public class BitmapUtils {
/**
*
* @param filePath 要加载的图片路径
*
* @param destWidth 显示图片的控件宽度
*
* @param destHeight 显示图片的控件的高度
*
*/
public static Bitmap getBitmap(String filePath, int destWidth, int destHeight) {
//第一次采样
BitmapFactory.Options options = new BitmapFactory.Options();
//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点
options.inJustDecodeBounds = true;
//第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点
BitmapFactory.decodeFile(filePath, options);
//获得原图的宽和高 int outWidth = options.outWidth;int outHeight = options.outHeight;
//定义缩放比例
int sampleSize = 1;
while (outHeight / sampleSize > destHeight || outWidth / sampleSize > destWidth) {
//如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例
//sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取值
sampleSize *= 2;
}
//至此,第一次采样已经结束,我们已经成功的计算出了sampleSize的大小
//二次采样开始//二次采样时我需要将图片加载出来显示,不能只加载图片的框架,因此inJustDecodeBounds属性要设置为false
options.inJustDecodeBounds = false;
//设置缩放比例
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//加载图片并返回
return BitmapFactory.decodeFile(filePath, options);
}}
喜欢的同学可以点赞支持博主!
参考博客:简书二次采样