Bitmap的高效加載,避免內存溢出

Android對單個應用有內存限制,比如16MB,這導致加載Bitmap時很容易出現內存溢出:

java.lang.OutofMemoryError:bitmap size exceeds VM budget

因此我們需要考慮如何高效加載bitmap,避免發生內存溢出。


首先回顧一下如何加載一個bitmap:

BitmapFactory提供了四類方法:decodeFile、decodeResource、decodeStream、decodeByteArray,其中decodeFile、decodeResource間接調用了decodeStream方法,這四類最終都是在android底層實現的。

那麼如何高效地加載bitmap呢?

採用BitmapFactory.Options來縮放圖片。以ImageView爲例,很多時候ImageView沒有原始圖片那麼大,將圖片整個加載進來再設給ImageView顯得沒有必要,因爲ImageView沒有辦法顯示原始的圖片。這時就可以通過BitmapFactory.Options按一定的採樣率來加載縮小後的圖片,這樣就會降低內存佔用從而在一定程度上避免OOM,提高了bitmap加載時的性能。

通過BitmapFactory.Options縮放圖片,主要用到它的inSampleSize參數,即採樣率。當inSampleSize爲1時,採樣後的圖片大小爲圖片的原始大小;當inSampleSize大於1時,比如2,那麼採樣後圖片的寬高均爲原圖大小的1/2,像素數爲原圖的1/4,其佔有的內存大小也爲原圖的1/4。inSampleSize必須大於1纔會有效果,並建議取值爲2的指數,比如1、2、4、8、16。


獲取並改變採樣率的方法:

1.將BitmapFactory.Options的inJustDecodeBounds參數設爲true,設置完以後,BitmapFactory在加載bitmap時就不會真正的去加載,只是去獲取圖片原始的寬高信息,這個操作是輕量級的。

2.通過BitmapFactory加載bitmap,這樣圖片原始的寬高信息就會存儲在Options裏面了。

3.根據圖片原始的寬高、ImageView的寬高(你需要的寬高)來計算合適的inSampleSize並賦給Options.inSampleSize。

4.將BitmapFactory.Options的inJustDecodeBounds參數設回false,重新加載bitmap。



代碼實現:

public static Bitmap decodeBitmap(Resources res, int resId, int reqWidth, int reqHeight){
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    //這裏必須採用傳入options的方法
    BitmapFactory.decodeResource(res, resId, options);

    int height = options.outHeight;
    int width = options.outWidth;
    int sampleSize = 1;
    while(height > reqHeight || width > reqWidth){
        sampleSize *= 2;
        height /= 2;
        width /= 2;
    }

    options.inSampleSize = sampleSize;
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章