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);