標籤:android blog io 使用 sp java for on div
因為手機的記憶體資源是有限的,每個app可使用的記憶體是受限的。而現在採用高解析度拍的照片往往很大。如果載入時不注意方法,很有可能會引起java.lang.OutofMemoryError: bitmap size exceeds VM budget. 異常而導致app奔潰退出。
另外ImageView支援的圖片大小也是受限制的,比如整個App雖然只放一張圖片,該圖片大小也沒超過整個app的記憶體上限。但該圖片大小超過了ImageView的最大值,這也是有問題的。這時需要採取方法,在載入圖片時縮小載入圖片的大小。具體的策略看下面的介紹。
在真正建立和載入(需要實際耗費記憶體)一個圖片對象時,我們可以先擷取映像的大小資訊。這裡我們可以用到BitmapFactory.Options這個類。BitmapFactory.Options這個類,有一個欄位叫做 inJustDecodeBounds 。SDK中對這個成員的說明是這樣的:
“If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.”
也就是說,如果我們把它設為true,那麼BitmapFactory.decodeFile(String path, Options opt)並不會真的返回一個Bitmap給你,但它會把它的寬,高等基本資料取回來給你,這樣就不會實際分配圖片所需的記憶體。代碼例子如下:
BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), R.drawable.pic1, options);String text = "imageHeight:" + options.outHeight + ",imageWidth:"+ options.outWidth + ",imageType:" + options.outMimeType;Toast.makeText(this, text, Toast.LENGTH_LONG).show();
知道了圖片的大小後,就可以考慮是將整個完整的圖片載入到記憶體中,或是將縮小版載入到記憶體中。因為手機螢幕本身大小就那麼大,沒必要將原尺寸的圖片載入進去。比如如果螢幕的大小為128x96,則將大小為1024x76的圖片載入進去就沒有意義。
為了告訴解碼器將圖片壓縮後載入到記憶體中,需要設定BitmapFactory.Options對象的 inSampleSize 屬性。比如,一張2048*1536的圖片,如果設定inSampleSize的值為4. 縮小後圖片的尺寸變為 512x384。佔用的記憶體由原來的12M變為0.75M。下面的方法可以計算出一個圖片應該設定的inSampleSize值:
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {// reqWidth、reqHeight是想要顯示圖片的大小,如螢幕的大小或ImageView控制項的大小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;while ((halfHeight / inSampleSize) > reqHeight&& (halfWidth / inSampleSize) > reqWidth) {inSampleSize *= 2;}}return inSampleSize;}
有了適當的inSampleSize值後,就可以真正的執行載入圖片的操作了。代碼如下:
final BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeResource(res, resId, options); ImageView imageView = (ImageView)findViewById(R.id.imageView1); imageView.setImageBitmap(bitmap);
實際上對於大的圖片,通過使用inSampleSize將圖片變小後載入到記憶體中,只要不是變了非常小,不會影響視覺效果。但來的好處是顯而意見的,會大大降低對記憶體的使用。一般對於大尺寸的照片(如用手機自身拍的),將inSampleSize設定為4一般不會影響視覺效果。
Android學習筆記:如何高效顯示圖片,避免記憶體溢出 和 ImageView無法顯示大尺寸的圖片