Drawable緩存問題,顯示清晰度,
Resource.getDrawable會根據ID傳回Drawable,然後把這個Drawable緩存起來,看以下這個代碼段:
InputStream is = mAssets.openNonAsset(
value.assetCookie, file, AssetManager.ACCESS_STREAMING);
// System.out.println("Opened file " + file + ": " + is);
dr = Drawable.createFromResourceStream(this, value, is,
file, null);
is.close();
dr.setChangingConfigurations(value.changingConfigurations);
cs = dr.getConstantState();
if (cs != null) {
if (mPreloading) {
sPreloadedDrawables.put(key, cs);
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached drawable @ #" +
// Integer.toHexString(key.intValue())
// + " in " + this + ": " + cs);
mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
}
}
}
緩存機制設計的很好,使用了弱引用機制避免記憶體溢出。但這個方法比較老實,如果資源是一張Bitmap的話,原圖是多大,它就會生成多大的。為了讓程式在不同的螢幕上面都比較清晰,并且圖檔占用記憶體不會過大,通常會根據不同的螢幕選擇加載不同的圖,但這樣包大小又上去了,一般,我們會用到這樣一個解決辦法:
隻放一張最大清晰度的圖,程式運作時根據目前螢幕尺寸對圖檔進行縮放。
這個辦法有一個缺點,就是加載時會先加載一張大圖,再根據大圖去生成小圖,記憶體峰值是兩張圖,在記憶體緊張的手機上有什麼辦法麼?下面是解決方案:
private BitmapDrawable getDrawable(int id) {
int width = AppTools.getSreenSize(this, true);
int height = AppTools.getSreenSize(this, false);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), id, opts);
opts.inSampleSize = AppTools.computeSampleSize(opts, -1,
(int) (width * height));
opts.inJustDecodeBounds = false;
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeResource(getResources(), id, opts);
} catch (OutOfMemoryError e) {
}
if (bitmap == null) {
return null;
}
return new BitmapDrawable(bitmap);
}
先使用擷取圖檔的寬高,然後根據目标寬高計算出采樣大小,最後再真正讀取圖檔。
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), id, opts);