Android-Bitmap优化

本文详细探讨了Android中Bitmap导致的内存溢出问题,并提供了内存优化的四个策略:编码、采样、复用和匿名共享内存(Ashmem)。通过调整Bitmap的编码格式,设置采样率,使用Bitmap复用以及利用LRU缓存来有效管理内存,从而避免OOM错误。同时,还介绍了Android 8.0之后Bitmap存储的变化和如何加载高清图片。
摘要由CSDN通过智能技术生成

概述

在日常开发中我们经常遇到加载图片报出oom的错误,我们要解决这个问题,首先要明白oom代表out of memory 内存溢出,因为手机内存有限,分给每个应用的内存有限,所以要解决这个问题就是要解决图片占用内存问题 android 中图片是以bitmap的形式存在的,那么bitmap中所占的内存,直接影响到了是否oom,我们了解一下bitmap的占用内存的计算方法

Bitmap到底占多大内存

从本地加载或者从网络加载可以用下面的公式计算

图片的长度 * 图片的宽度 * 一个像素点占用的字节数

如果从资源文件夹加载,会怎么样?

首先把同一张图片放进不同的资源文件夹会发生什么?

  • 同一张图片放进不同的文件夹,图片会被压缩

看下源码

if (env->GetBooleanField(options, gOptions_scaledFieldID)) {
    const int density = env->GetIntField(options, gOptions_densityFieldID);
    const int targetDensity = env->GetIntField(options, gOptions_targetDensityFieldID);
    const int screenDensity = env->GetIntField(options, gOptions_screenDensityFieldID);
    if (density != 0 && targetDensity != 0 && density != screenDensity) {
        scale = (float) targetDensity / density;
    }
}
...
int scaledWidth = decoded->width();
int scaledHeight = decoded->height();

if (willScale && mode != SkImageDecoder::kDecodeBounds_Mode) {
    scaledWidth = int(scaledWidth * scale + 0.5f);
    scaledHeight = int(scaledHeight * scale + 0.5f);
}
...
if (willScale) {
    const float sx = scaledWidth / float(decoded->width());
    const float sy = scaledHeight / float(decoded->height());
    bitmap->setConfig(decoded->getConfig(), scaledWidth, scaledHeight);
    bitmap->allocPixels(&javaAllocator, NULL);
    bitmap->eraseColor(0);
    SkPaint paint;
    paint.setFilterBitmap(true);
    SkCanvas canvas(*bitmap);
    canvas.scale(sx, sy);
    canvas.drawBitmap(*decoded, 0.0f, 0.0f, &paint);
}

我们可以看到压缩比例是由下面的公式得出

 scale = (float) targetDensity / density;

及缩放的比例和targetDensity,density有关,那么这个俩个变量又代表着什么呢?

  • targetDensity:设备屏幕像素密度 dpi
  • density:图片对应的文件夹的像素密度 dpi

其中density和Bitmap存放的资源目录有关,不同的资源目录有不同的值

density 0.75 1 1.5 2 3 3.5 4
densityDpi 120 160 240 320 480 560
DpiFolder ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi

可以得出以下结论

  • 同一张图片放在不同的资源目录下,其分辨率会有变化
  • Bitmap的分辨率越高,其解析后的宽高越小,甚至小于原有的图片(及缩放),从而内存也响应的减少
  • 图片不放置任何资源目录时,其使用默认分辨率mdpi:160
  • 资源目录分辨率和屏幕分辨率一致时,图片尺寸不会缩放

所以Bitmap在资源目录中的计算方式为

Bitmap内存占用 ≈ 像素数据总大小 = 图片宽 × 图片高× (当前设备密度dpi/图片所在文件夹对应的密度dpi)^2 × 每个像素的字节大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值