Android加載大背景圖或者大量圖片時,內存溢出的解決方案

Android在加載大背景圖或者大量圖片時,常常致使內存溢出(Out of Memory Error),解決方案以下:java

一,3種在代碼中設置圖片方式有區別,最好不使用setImageResource,緣由:
(1)setImageResource的參數是resId,必須是drawable目錄下的資源.在UI線程中對圖片讀取和解析的,因此有可能對一個Activity的啓動形成延遲。
(2)setImageDrawable參數是Drawable,也是能夠接受不一樣來源的圖片,方法中所作的事情就是更新ImageView的圖片。
(3)setImageBitmap參數是Bitmap,把Bitmap對象封裝成Drawable對象,而後調用setImageDrawable來設置圖片。android

二,BitmapFactory提供了幾種解碼方式(decodeByteArray(), decodeFile(), decodeResource(),decodeStream()等等),以便從多種資源中建立一個Bitmap(位圖)對象。
建議使用decodeStream(),最節省空間,由於它直接調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap。git

    /**
     * 對一張大圖片進行適當的壓縮,讓它可以以最佳大小顯示的同時,還能防止OOM的出現。
     * @param path SD卡中的圖片的路徑
     * @param reqWidth reqHeight 壓縮圖片的尺寸,單位是像素(sp)
     */
    public static Bitmap getLimitSizeBitmapFromPath(String path, int reqWidth, int reqHeight) 
      throws IOException{
         //1.加載位圖
         FileInputStream is = new FileInputStream(path);
         BitmapFactory.Options opts=new BitmapFactory.Options();
     
         //2.設置位圖縮放比例
         opts.inJustDecodeBounds = true;
        // 當inJustDecodeBounds = true時,decodeFile禁止爲bitmap分配內存,返回值也再也不是一個Bitmap對象,而是null
        // 可是BitmapFactory.Options的outWidth、outHeight和outMimeType屬性都會被賦值
        Bitmap bitmap = BitmapFactory.decodeFile(path, opts);
        final int height = opts.outHeight;
        final int width = opts.outWidth;       
        int scale = 1;
        if (height > reqHeight || width > reqWidth) {
           // 計算出實際寬高和目標寬高的比率
           final int heightRatio = Math.round((float) height / (float) reqHeight);
           final int widthRatio = Math.round((float) width / (float) reqWidth);
           // 選擇寬和高中最小的比率做爲inSampleSize的值,這樣能夠保證最終圖片的寬和高
           // 必定都會大於等於目標的寬和高。
           scale = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        opts.inSampleSize = scale;
        opts.inJustDecodeBounds = false;
     
        //3.設置位圖顏色顯示優化方式
        //ALPHA_8:每一個像素佔用1byte內存(8位)
        //ARGB_4444:每一個像素佔用2byte內存(16位)
        //ARGB_8888:每一個像素佔用4byte內存(32位),Android默認的顏色模式,佔用的內存也最大
        //RGB_565:每一個像素佔用2byte內存(16位)
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
 
        //4.設置圖片能夠被回收,建立Bitmap用於存儲Pixel的內存空間在系統內存不足時能夠被回收
        opts.inPurgeable = true;
     
        //5.設置解碼位圖的尺寸信息
        opts.inInputShareable = true;
 
        //6.解碼位圖:decodeStream是最節省空間的一種方法
        bitmap = BitmapFactory.decodeStream(is, null, opts);
 
        is.close();
        return bitmap;
    }

三,若是使用imageView.setImageBitmap()來加載圖片,在Activity或者Fragment在onStop/onDestroy釋放圖片資源。github

if(imageView != null) {

    BitmapDrawable b = (BitmapDrawable)v.getDrawable();

    if(b != null){     

        Bitmap oldBitmap = b.getBitmap();    

        if(oldBitmap != null && !oldBitmap.isRecycled()){    

            oldBitmap.recycle();    

            oldBitmap = null;

        }    

    }

}

四,若是使用imageView.setImageDrawable()來加載圖片,在Activity或者Fragment在onStop/onDestroy釋放圖片資源。緩存

if(imageView != null) {

    Drawable d = (ImageView).getDrawable();

    if (d != null) {

     //清除setImageDrawable(d)對d的引用

     d.setCallback(null);

    }

    ImageView.setImageDrawable(null);

}

此外,介紹下面幾個開源框架,都包含了很好的圖片緩存功能:框架

1. thinkandroid:API 4(Android 1.6)以上
項目地址 https://github.com/white-cat/ThinkAndroid優化

2. Afinal
項目地址 https://github.com/yangfuhai/afinal線程

3. KJFrameForAndroid: API 11(Android 3.0)以上
項目地址 https://github.com/kymjs/KJFrameForAndroidcode

4. volley: API 8(Android 2.2)以上
Demo地址 https://github.com/smanikandan14/Volley-demo對象

5. xUtils框架: API 8(Android 2.2)以上
項目地址:https://github.com/wyouflf/xUtils

6. LoonAndroid: API 8(Android 2.2)以上
項目地址:https://github.com/gdpancheng/LoonAndroid

相關文章
相關標籤/搜索