Android中Bitmap的使用

Bitmap使用需要注意哪些问题 ?

  1. 要选择合适的图片规格(bitmap类型):通常我们优化Bitmap时,当需要做性能优化或者防止OOM,==我们通常会使用RGB_565==,因为ALPHA_8只有透明度,显示一般图片没有意义,Bitmap.Config.ARGB_4444显示图片不清楚,Bitmap.Config.ARGB_8888占用内存最多。:
  • ALPHA_8 每个像素占用1byte内存
  • ARGB_4444 每个像素占用2byte内存
  • ARGB_8888 每个像素占用4byte内存(默认)
  • RGB_565 每个像素占用2byte内存
  1. 降低采样率:BitmapFactory.Options 参数inSampleSize的使用,先把options.inJustDecodeBounds设为true,只是去读取图片的大小,在拿到图片的大小之后和要显示的大小做比较通过calculateInSampleSize()函数计算inSampleSize的具体值,得到值之后。options.inJustDecodeBounds设为false读图片资源。
  2. 复用内存:即通过软引用(内存不够的时候才会回收掉),复用内存块,不需要再重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。
  3. 使用recycle()方法及时回收内存。
  4. 压缩图片。

Bitmap.recycle()会立即回收么?什么时候会回收?如果没有地方使用这个Bitmap,为什么垃圾回收不会直接回收?

  • 加载Bitmap到内存里以后,是包含两部分内存区域的。简单的说,一部分是Java部分的,一部分是C部分的。这个Bitmap对象是由Java部分分配的,不用的时候系统就会自动回收了。
  • 但是那个对应的C可用的内存区域,虚拟机是不能直接回收的,这个只能调用底层的功能释放。所以需要==调用recycle()方法来释放C部分的内存==
  • bitmap.recycle()方法用于回收该Bitmap所占用的内存,接着将bitmap置空,最后使用System.gc()调用一下系统的垃圾回收器进行回收,调用System.gc()并不能保证立即开始进行回收过程,而只是为了加快回收的到来。

一张Bitmap所占内存以及内存占用的计算

  • Bitamp 所占内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存字节大小

注:这里inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi,所以你可以发现inDensity和inTargetDensity会对Bitmap的宽高进行拉伸,进而改变Bitmap占用内存的大小。

  • 在Bitmap里有两个获取内存占用大小的方法。
  1. getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。
  2. getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。
  3. 在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。在通过复用 Bitmap 来解码图片时,那么 getByteCount() 表示新解码图片占用内存的大 小,getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小。

图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处理?

首先我们要清楚图片的三级缓存是如何的

image.png

如果内存足够时不回收。内存不够时就回收软引用对象。

内存中如果加载一张500*500的png高清图片.应该是占用多少的内存?

不考虑屏幕比的话:占用内存=500 * 500 * 4 = 1000000B ≈ 0.95MB
考虑屏幕比的的话:占用内存= 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存字节大小
inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi

image.png

Bitmap如何处理大图,如一张30M的大图,如何预防OOM?

避免OOM的问题就需要对大图片的加载进行管理,主要通过缩放来减小图片的内存占用。

  • BitmapFactory提供的加载图片的四类方法(decodeFile、decodeResource、decodeStream、decodeByteArray)都支持BitmapFactory.Options参数==,通过inSampleSize参数就可以很方便地对一个图片进行采样缩放==
  • 比如一张10241024的高清图片来说。那么它占有的内存为102410244,即4MB,如果inSampleSize为2,那么采样后的图片占用内存只有512512*4,即1MB(注意:根据最新的官方文档指出==,inSampleSize的取值应该总是为2的指数==,即1、2、4、8等等,如果外界输入不足为2的指数,系统也会默认选择最接近2的指数代替,比如2)
  • 综合考虑。通过采样率即可有效加载图片,==流程如下==
  1. 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片
  2. 从BitmapFactory.Options中取出图片的原始宽高信息,它们对应outWidth和outHeight参数
  3. 根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
  4. 将BitmapFactory.Options的inJustDecodeBounds参数设为false,重新加载图片。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vinson武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值