今天给大家带来2017年第一篇技术文章, 是一篇关于图片处理的文章。
背景:图片加载在项目中是随处可见,而图片加载在很多情况下需要用到Bitmap(位图)这个类。Bitmap可以说是一个“大胖子”,因为Bitmap自身会将图片每个像素的属性全部保存在内存中。这就会导致我们稍有不慎就会创建出一个占用内存很大的Bitmap对象,从而导致加载速度过慢,常见表现为OOM(Out of Memory)。 有必要对Bitmap进行优化,从而降低出现Crash情况的概率,提高app的加载图片速度,增强APP稳定性。
1
应用场景
举个栗子
上面的代码经常在我们的项目中出现。你可知其背后的处理逻辑?
根据源码可知,上面的代码中两个方法setBackgroundResource()
和setImageResource()
是使用Bitmap作为过渡处理的。在运行时,上面的两个方法会使用BitmapFactory.decodeStream()方法将资源图片生成一个Bitmap,然后由这个Bitmap生成一个Drawable,最后再将这个Drawable设置到ImageView。
如果运用以上代码,在加载的图片的尺寸远大于ImageView的尺寸,你会发现控件加载图片非常缓慢。你使用在ListView或RecycleView中批量加载一些未知size的图片的时候,你会发现会出现卡顿的情况。
2
BitmapFactory
BitmapFactory是谷歌官方为我们开发者提供加载图片方式的类,它可以从文件、图片传输流、字节数组这三种方式中加载图片。
3
Options类介绍
要实现高效加载Bitmap,首先我们要了解Options类的几个参数,因为正是通过合理的配置这几个参数,我们才能够实现高效的加载Bitmap对象。Options类是BitmapFactory的一个静态内部类,我们来看一下它的源码:
几个名词解释下:
density
:可以理解为相对屏幕密度,我们知道,1个DIP在160dpi的屏幕上大约为1像素大小。我们以160dpi为基准线,density的值即为相对于160dpi屏幕的相对屏幕密度。比如,160dpi屏幕的density值为1, 320dpi屏幕的density值为2
densityDpi
:可以理解为绝对屏幕密度,也就是实际的屏幕密度值(dots per inch),比如160dpi屏幕的densityDpi值就是1604
Bitmap优化
1.获取图片的原始宽高 通过将Options的inJustDecodeBounds属性设为true后调用decodeResource方法,可以实现不真正加载图片而只是获取图片的尺寸信息
2、根据原始宽高计算出inSampleSize,代码如下:
3、根据计算出的inSampleSize生成Bitmap
4、调用以上的decodeSampledBitmapFromResource方法,使用自定尺寸的Bitmap。 如果你要将一张大图设置为一个250*250的缩略图,执行以下代码:
作者:猴哥,公众号:极客猴。爱好读书,喜欢钻研技术,梦想成为文艺青年的IT Boy。
- END -