圖片緩存架構
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
中貼出的地址