图片缓存架构
BitMap创建方式
1.BitMapFactory.decodeResoure() 最消耗资源,因为他会根据手机屏幕进行适配(慎用,比较消耗性能最大的)
//第一步
if (opts == null) {
opts = new Options();
}
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
}
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}
//第二步
bm = nativeDecodeAsset(asset, outPadding, opts);
2.BitMapFactory.decodeFile()(推荐,是通过调用native方式创建BitMap,消耗性能最少)
//Jni调用
private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
// ASSERT(is != null);
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
return nativeDecodeStream(is, tempStorage, outPadding, opts);
}
3.BitMapFactory.decodeByteArray()(推荐,是通过调用native方式创建BitMap,消耗性能最少)
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
if ((offset | length) < 0 || data.length < offset + length) {
throw new ArrayIndexOutOfBoundsException();
}
Bitmap bm;
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
try {
bm = nativeDecodeByteArray(data, offset, length, opts);
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
}
return bm;
}
BitMap创建与优化
1.BitmapFactory.decodeFile()
2.BitmapFactory.Options options= new BitmapFactory.Options();
options.inPreferredConfig配置
BitMap大图片的处理
1.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
2.如果我们有个图片是1024*768的图片显示在128*60的ImageView是毫无意义的,那么我们应该如何出处理呢?谷歌官方压缩的算法处理如下:
//计算出最优的压缩值
//参数1 :Options对象 参数2:请求的宽(ImageView的宽度) 参数3:请求的高度(ImageView的高度)
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
3.真正的使用
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
//如果自己手动设置压缩比,最好是设置为2的倍数,如果压缩比是2,那么图片压缩成1/4
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
Android开发文档地址
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
BitMap各个版本的实现机制
内存资源回收: Android 2.3(API Level 10)- 由于存储图像数据的Buffer分配在Native内存中, 并且只能通过 recycle( ) 来显式释放Buffer , 而3.0+中,该Buffer则分配在Dalvik Heap中, 因此 recycle( ) 通常当成兼容向下版本的调用. p.s. 该Buffer可在Android源码Bitmap.java中找到.
内存重利用: 3.0+允许开发者将已存在的Bitmap.Buffer分配给新的Bitmap来使用, 不过Bitmap之间的大小要严格相同, 而4.4(API Level 19)+则改变这一状况.
*BitmapFactory.Options: 详见SDK API Reference.
扩展阅读
上述都只是针对单个Bitmap的内存管理, 但是在开发中, 难免会需要管理大量的Bitmap, 那应该怎么办?
在API Level 12中, 可以通过LruCache来缓存大量的内存Bitmap. 除此之外, 在Android源码中, 可以找到, 一个名为DiskLruCache的类, 它可以文件形式缓存Bitmap.
LruCache和DiskLruCache类可以参考
http://blog.csdn.net/hello_word1024/article/details/51638770
中贴出的地址