Android Bitmap的加载与缓存

  Android中图片资源非常的耗内存,当图片超过一定大小时就会出现OOM(Out Of Memory)异常。关于图片的加载优化,主要有采样压缩、缓存策略、异步加载等。

1. Bitmap加载方式

Bitmap有四种加载方式:

  • BitmapFactory.decodeStream():以文件流方式
  • BitmapFactory.decodeResource():以资源ID方式
  • BitmapFactory.decodeFile():以文件路径方式
  • BitmapFactory.decodeByteArray():以字节数组方式
  1. 以文件流方式加载
//图片在sdcard中
String filePath = "/sdcard/pic/test.png";
FileInputStream in = null;
try {
    in = new FileInputStream(filePath);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(in);

//图片在Assets目录
String fileName = "sample.png";
InputStream in = getResources().getAssets().open(fileName);
Bitmap bitmap = BitmapFactory.decodeStream(in);

//图片在src目录
String filePath = "com/example/bitmap/test.png";
InputStream in = getClassLoader().getResourceAsStream(path);
Bitmap imageBitmap3 = BitmapFactory.decodeStream(in);
  1. 以资源ID方式加载
 Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);

 //不推荐使用getDrawable()方式,该方法已经过时了
BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.ic_launcher_foreground);
Bitmap bitmap = bitmapDrawable.getBitmap();
  1. 以文件路径方式加载
// 方法1
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);

//方法2:效率更高
FileInputStream fis = new FileInputStream(filePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
  1. 以字节数组方式加载
byte[] data = new byte[1024];
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);

2. Bitmap常用参数

BitmapFactory.Options参数主要有:

  • inJustDecodeBounds :值为true,不返回bitmap,不分配内存,只返回bitmap的尺寸
  • outWidth & outHeight :获取获取图片的宽度、高度
  • inSampleSize :图片缩放的倍数,值为1表示不压缩
  • inDensity :位图的像素压缩比

Bitmap.Config inPreferredConfig中的变量位数越高代表其可以存储的颜色信息越多,图像越逼真,选项有:

  • ALPHA_8 :8位位图,每个像素占1个字节内存,它不存储颜色信息
  • RGB_565 :16位位图,每个像素占2个字节内存,并且仅对RGB通道进行编码:红色存储5位精度,绿色存储6位精度,蓝色存储5位精度
  • ARGB_4444 :16位位图,每个像素占2个字节内存,三个RGB颜色通道和alpha通道以4位精度存储(已经过时)
  • ARGB_8888 :32位位图,每个像素占4个字节内存,每个通道以8位精度存储
  • RGBA_F16 :64位位图,每个像素占8个字节内存,每个通道都存储为半精度浮点值
  • HARDWARE :当需要在屏幕绘制位图时,最好选择此选项

示例代码如下:

@RequiresApi(api = Build.VERSION_CODES.O)
public static Bitmap decodeBitmapFromResource(String filePath, int reqWidth, int reqHeight) {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    //不返回bitmap,只返回这个bitmap的尺寸
    options.inJustDecodeBounds = true;
    //图片存储像素
    options.inPreferredConfig = Bitmap.Config.RGBA_F16;
    //预加载
    BitmapFactory.decodeFile(filePath, options);
    //计算出缩放比inSampleSize,只能是2的整数次幂
    options.inSampleSize = getSampleSize(options, reqWidth, reqHeight);
    //返回bitmap
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(filePath, options);
}

public static int getSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqHeight) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;
        while ((halfHeight / inSampleSize >= reqHeight) && (halfWidth / inSampleSize >= reqWidth)) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

3. Bitmap缓存策略

  • android LruCache:内存缓存,读取速度最快。内部采用LinkedHashMap进行实现
  • android DiskLruCache:硬盘缓存或文件缓存,读取速度比内存缓存稍慢
  • 网络缓存,利用第三方插件进行,读取速度最慢
  • SQLite数据库保存或SharedPreferences保存

Android中关于几种常用的图片加载库的使用可查看:Android中几种常用图片加载库的使用

原创文章 38 获赞 13 访问量 4021

猜你喜欢

转载自blog.csdn.net/qq_36287943/article/details/105300791
今日推荐