习惯性的开始之前,美图镇楼
在实际开发过程中,我们经常会遇到所开发的APP加载缓慢甚至卡顿的问题,很大一部分原因就是图片造成的,这篇文章将对Android的图片进行优化以实现对性能的优化。
Android图片OOM问题的产生
可能的原因有以下3点:
- 一个页面一次加载过多的图片。 可能少量的图片加载对性能没有多大的影响,但是大量的图片对内存的占用是很可观的,而每个APP都是有内存限制的,大量的图片加载就可能直接超过了APP的内存限制,而直接OOM;
- 加载大图片没有进行压缩(尺寸,质量)。 对于大图片直接使用imageView.setImageResource()是不行的,需要对尺寸或质量进行优化;
- Android列表加载大量bitmap没有使用缓存。 需要使用缓存重用或者比较流行的图片加载框架如Glide,Fresco等,也是自带缓存功能的。
如何计算一张图片占用的内存?
一张图片占用的内存 = 图片的高度 * 图片的宽度 * 一个像素所占的内存
从这里我们就可以看出,对于图片优化可以从以下3个方面入手:
-
尺寸压缩; ps:就是减小图片的宽高。
BitmapFactory.Options里面有个inJustDecodeBounds设置为true,就可以在不加载图片内存的情况下获取图片的宽高。从而计算出合适的压缩比inSampleSize,设置inSampleSize大于等于2,就可以降低图片的采样率,从而减小内存的占用。如果我们单纯的改变ImageView的大小不会对图片占用的内存有任何的优化作用,因为图片是存储在bitmap里面,只有对bitmap本身的优化才会起作用。 -
质量压缩; ps:就是改变一个像素占用的内存,内部是通过优化解码率来实现的。
也就是解码率压缩,常见的PNG,JPG,WEBP等格式的图片在设置到UI上之前经过解码过程。通过解码率方面优化图片占用内存的方式:使用RGB_565替代ARGB_8888可以降低图片占用内存。因为它可以降低一个像素占用的内存大小,RGB_565的一个像素占2个字节,而ARGB_8888一个像素占4个字节。 -
内存重用; ps:可以通过Android提供的InBitmap来实现。
InBitmap是Android3.0之后才能用的,使用了InBitmap的图片的内存大小是小于或者等于没有使用的图片内存大小。
代码演示(原图加载)
/**
* 加载原图
* @param img 目标ImageView控件
* @param filePath 图片路径
*/
private void loadOriginalSize(ImageView img, String filePath) {
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
img.setImageBitmap(bitmap);
}
代码演示(图片压缩)
/**
* 压缩图片
* @param img
* @param filePath
*/
private void picOptimize(ImageView img, String filePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
//设置为true,就可以在不加载图片内存的情况下获取图片的宽高
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
//获取图片宽度
int width = options.outWidth;
//计算出合适的压缩比,width压缩到200px
options.inSampleSize = width / 200;
//降低每个像素所占的内存大小,一个像素只占用两个字节
options.inPreferredConfig = Bitmap.Config.RGB_565;
//真正把压缩后的图片加载出来
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
img.setImageBitmap(bitmap);
}
}
代码演示(内存重用)
/**
* inBitmap的使用,内存重用
* @param secondImg 第二张图片的控件
* @param filePath 第二张图片的路径
* @param firstBitmap 第一张图片的bitmap(第二张图片的内存将重用这个bitmap的内存)
*/
private void picInBitmap(ImageView secondImg, String filePath, Bitmap firstBitmap) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inBitmap = firstBitmap;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
secondImg.setImageBitmap(bitmap);
}
好了,图片的内存优化就到这里,后续还有关于图片缓存,懒加载的文章,关注我查看对应的文章。