这篇文章主要介绍“如何高效利用Bitmap”,在日常操作中,相信很多人在如何高效利用Bitmap问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何高效利用Bitmap”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
背景:图片加载在项目中是随处可见,而图片加载在很多情况下需要用到Bitmap(位图)这个类。Bitmap可以说是一个“大胖子”,因为Bitmap自身会将图片每个像素的属性全部保存在内存中。这就会导致我们稍有不慎就会创建出一个占用内存很大的Bitmap对象,从而导致加载速度过慢,常见表现为OOM(Out of Memory)。
有必要对Bitmap进行优化,从而降低出现Crash情况的概率,提高app的加载图片速度,增强APP稳定性。
举个栗子
上面的代码经常在我们的项目中出现。你可知其背后的处理逻辑?
根据源码可知,上面的代码中两个方法setBackgroundResource()
和setImageResource()
是使用Bitmap作为过渡处理的。在运行时,上面的两个方法会使用BitmapFactory.decodeStream()方法将资源图片生成一个Bitmap,然后由这个Bitmap生成一个Drawable,最后再将这个Drawable设置到ImageView。
如果运用以上代码,在加载的图片的尺寸远大于ImageView的尺寸,你会发现控件加载图片非常缓慢。你使用在ListView或RecycleView中批量加载一些未知size的图片的时候,你会发现会出现卡顿的情况。
BitmapFactory是谷歌官方为我们开发者提供加载图片方式的类,它可以从文件、图片传输流、字节数组这三种方式中加载图片。
要实现高效加载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值就是160
缩放系数
Options类中存在一个inScaled参数,这个参数表示是否支持缩放,我们从Options的默然构造方法中可以看到这个参数被初始化为了true,也就是说默认是支持缩放的。那么将如何进行缩放呢?答案是根据缩放系数进行缩放。关于缩放系数的计算方法,其实我们在讲解如何计算内存中Bitmap的大小时已经介绍过了。缩放系数就是inTargetDensity除以inDensity。inDensity表示我们的图片所处的资源文件夹对应的dpi,inTargetDensity表示目标设备的屏幕密度。
采样率(inSampleSize)
当这个参数为1时,采样后的图片大小和原来一样;当这个参数为2时,采样后的图片宽高均为原来的1/2,大小也就成了原来的1/4。也就是说,采样后的大小等于原始大小除以采样率的平方。官方文档规定,inSampleSize的值应为2的非负整数次幂(1,2,4,… ),否则会被系统向下取整并找到一个最接近的值。通过设置inSampleSize我们就能够将图片缩放到一个合理的大小
1.获取图片的原始宽高
通过将Options的inJustDecodeBounds属性设为true后调用decodeResource方法,可以实现不真正加载图片而只是获取图片的尺寸信息
2、根据原始宽高计算出inSampleSize,代码如下:
3、根据计算出的inSampleSize生成Bitmap
4、调用以上的decodeSampledBitmapFromResource方法,使用自定尺寸的Bitmap。 如果你要将一张大图设置为一个250*250的缩略图,执行以下代码:
到此,关于“如何高效利用Bitmap”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。