美文网首页
Bitmap整理

Bitmap整理

作者: 卡路fly | 来源:发表于2020-05-22 02:45 被阅读0次

    getAllocationByteCount

    Bitmap.getAllocationByteCount() 方法获取 Bitmap 占用的字节大小

    默认情况下 BitmapFactory 使用 Bitmap.Config.ARGB_8888 的存储方式来加载图片内容,而在这种存储模式下,每一个像素需要占用 4 个字节。

    将同一张图片移动到drawable-hdpi下,Bitmap所占空间上涨原因:

    实际上 BitmapFactory 在解析图片的过程中,会根据当前设备屏幕密度和图片所在的 drawable 目录来做一个对比,根据这个对比值进行缩放操作。

    • 缩放比例 scale = 当前设备屏幕密度 / 图片所在 drawable 目录对应屏幕密度
    • Bitmap 实际大小 = 宽 * scale * 高 * scale * Config 对应存储像素数

    在 Android 中,各个 drawable 目录对应的屏幕密度分别为下:


    加载优化

    1. 修改图片加载的 Config
      修改占用空间少的存储方式可以快速有效降低图片占用内存。比如通过 BitmapFactory.Options 的 inPreferredConfig 选项,将存储方式设置为 Bitmap.Config.RGB_565。这种存储方式一个像素占用 2 个字节,所以最终占用内存直接减半。

    ALPHA_8 代表8位Alpha位图
    ARGB_4444 代表16位ARGB位图
    ARGB_8888 代表32位ARGB位图
    RGB_565 代表16位RGB位图

    【1个字节 = 8 bit 比特(位)】,一张15001000像素,使用ARGB_8888,每个像素点占用4个字节,总内存是15001000*4字节,5.7MB

    1. inSampleSize 参数,可以实现 Bitmap 采样压缩,这个参数的含义是宽高维度上每隔 inSampleSize 个像素进行一次采集。

    当inSampleSize为2时,一个2000 * 1000的图片,将被缩小为1000 * 500,相应地,它的像素数和内存占用都被缩小为了原来的1/4

    为了设置合适大小的inSampleSize,我们需要获取原始Bitmap的宽高,因此可以通过BitmapFactory进行获取。
    BitmapFactory提供了多个解析方法用于创建Bitmap对象,我们应该根据图片的来源选择合适的方法。比如SD卡中的图片可以使用decodeFile方法,网络上的图片可以使用decodeStream方法,资源文件中的图片可以使用decodeResource方法

    Android为每一种解析方法都提供了一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true,就可以让解析方法禁止为Bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。但是BitmapFactory.OptionsoutWidthoutHeightoutMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。如下代码所示:

    Bitmap复用

    1. 使用 Options.inBitmap 优化
      实际上经过第一次显示之后,内存中已经存在了一个 Bitmap 对象。每次切换图片只是显示的内容不一样,我们可以重复利用已经占用内存的 Bitmap 空间,具体做法就是使用 Options.inBitmap 参数。


    PS: Options.inMutable 置为 true,这里如果不置为 true 的话,BitmapFactory 将不会重复利用 Bitmap 内存

    复用 inBitmap 之前,需要调用 canUseForInBitmap方法来判断 reuseBitmap 是否可以被复用。这是因为 Bitmap 的复用有一定的限制:

    • 在 Android 4.4 版本之前,只能重用相同大小的 Bitmap 内存区域;
    • 4.4 之后可以重用任何 Bitmap 的内存区域,只要这块内存比将要分配内存的 bitmap 大就可以。

    BitmapRegionDecoder 图片分片显示

    在不压缩图片的前提下,不建议一次性将整张图加载到内存,而是采用分片加载的方式来显示图片部分内容,然后根据手势操作,放大缩小或者移动图片显示区域。

    BitmapRegionDecoder 将图片加载到内存中,图片可以以绝对路径、文件描述符、输入流的方式传递给 BitmapRegionDecoder



    Bitmap 缓存

    当需要在界面上同时展示一大堆图片的时候,比如 ListView、RecyclerView 等,由于用户不断地上下滑动,某个 Bitmap 可能会被短时间内加载并销毁多次。这种情况下通过使用适当的缓存,可以有效地减缓 GC 频率保证图片加载效率,提高界面的响应速度和流畅性。

    LruCache

    • 图中 1 处指定 LruCache 的最大空间为 20M,当超过 20M 时,LruCache 会根据内部缓存策略将多余 Bitmap 移除。
    • 图中 2 处指定了插入 Bitmap 时的大小,当我们向 LruCache 中插入数据时,LruCache 并不知道每一个对象会占用大多内存,因此需要我们手动指定,并且根据缓存数据的类型不同也会有不同的计算方式。

    LruCache原理

    LruCache(Least Recently Used)算法的核心思想就是最近最少使用算法

    内部维护了一个LinkHashMap的链表,通过put数据的时候判断是否内存已经满了,如果满了,则将最近最少使用的数据给剔除掉,从而达到内存不会爆满的状态。

    相关文章

      网友评论

          本文标题:Bitmap整理

          本文链接:https://www.haomeiwen.com/subject/yuhfahtx.html