Bitmap高效加載

Android對單個應(yīng)用的內(nèi)存分配是有限制的,比如16M,這樣就導(dǎo)致在加載Bitmap時很容易就導(dǎo)致OOM(out of menory 內(nèi)存溢出)。

內(nèi)存溢出(out of memory)通俗理解就是內(nèi)存不夠,就是所需要的內(nèi)存達到或超出系統(tǒng)為應(yīng)用分配的大小。

為了解決Bitmap對內(nèi)存造成的困擾,我們需要比較高效的加載Bitmap的策略。


對于Bitmap高效加載,我們先談?wù)?strong>Bitmap的加載。

Bitmap在Android中指的是一張圖片。加載一張圖片我們使用的是Android中 BitmapFactory 類中的方法。BitmapFactory中提供了四類方法:decodeFile,decodeResoure,decodeStream,decodeByteArry。分別可以從文件系統(tǒng),資源,輸入流,及字節(jié)數(shù)組中加載一個Bitmap對象。其中decodeFile,decodeResoure又間接調(diào)用decodeStream方法。這四類方法最終是在Android的底層實現(xiàn)的,對應(yīng)著BitmapFactory類的幾個native方法。


再來談?wù)劯咝Ъ虞d圖片,核心思想就是改變Bitmap的采樣率--inSampleSize。因為我們很多時候顯示的圖片并不需要加載圖片的原始尺寸,我們只需要將圖片按一定比例縮小后顯示即可。這樣在一定程度上降低加載圖片的內(nèi)存,減少了OOM的風(fēng)險。

高效加載Bitmap的一般步驟如下:

1.將BitmapFactory.options的inJustDecodeBonds參數(shù)設(shè)置為true。

2.從BitmapFactory.options中取出圖片的原始寬高信息。

3.根據(jù)目標View的大小結(jié)合原始寬高信息得出相對應(yīng)的采樣率,并設(shè)置還給BitmapFactory.options的inSampleSize。

4.將BitmapFactory.options的inJustDecodeBonds參數(shù)設(shè)置為true。并重新加載圖片。

inJustDecodeBonds參數(shù),設(shè)置為true時, BitmapFactory只會加載 圖片的原始寬高信息,并不會真正加載圖片,所以這個操作是輕量級的。

注意:BitmapFactory獲取的圖片寬高信息和圖片的位置以及程序運行的設(shè)備有關(guān),比如同一張圖片放在不同的drawable目錄下或者程序運行在不同屏幕密度的設(shè)備上,都可能導(dǎo)致BitmapFactory獲取到不同的結(jié)果,和Android的資源加載機制有關(guān)。

inSampleSize,即采樣率,通過對 inSampleSize的設(shè)置,對圖片的像素的高和寬進行縮放。

當inSampleSize=1,即采樣后的圖片大小為圖片的原始大小。小于1,也按照1來計算。 當inSampleSize>1,即采樣后的圖片將會縮小,縮放比例為1/(inSampleSize的二次方)。inSampleSize的取值應(yīng)該總是2的指數(shù),如1,2,4,8等。如果外界傳入的inSampleSize的值不為2的指數(shù),那么系統(tǒng)會向下取整并選擇一個最接近2的指數(shù)來代替。比如3,系統(tǒng)會選擇2來代替(開發(fā)建議)。

注意:通常需要根據(jù)圖片寬高實際的大小/需要的寬高大小,分別計算出寬和高的縮放比。但應(yīng)該取其中最小的縮放比,避免縮放圖片太小,到達指定控件中不能鋪滿,需要拉伸從而導(dǎo)致模糊。

下面是對上面四個步驟的實現(xiàn):

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        //加載圖片
        BitmapFactory.decodeResource(res,resId,options);
        //計算縮放比
        options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
        //重新加載圖片
        options.inJustDecodeBounds =false;
        return BitmapFactory.decodeResource(res,resId,options);
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 1;
        if(height>reqHeight||width>reqWidth){
            int halfHeight = height/2;
            int halfWidth = width/2;
            //計算縮放比,是2的指數(shù)
            while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
                inSampleSize*=2;
            }
        }


        return inSampleSize;

到這里就可以方便的加載縮放后的圖片了:

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.bitmap,100,100);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容