Android 內存管理--------------圖片太大內存溢出

在循環內儘量不要使用局部變量。
2.不用的對象可以把它指向NULL,並注意自己的代碼質量。
3.顯示讓系統GC回收 (這裏補充一下System.ge() 也不能隨便的調用,要考慮實際情況儘量在一次耗資源操作結束後纔去調用,或者有個調度的機制去判斷,因爲gc會佔用cpu導致程式響應變慢。


if(bitmapObject.isRecycled()==false) //如果沒有回收 
         bitmapObject.recycle();  //http://www.cnblogs.com/tankaixiong/
4.對大型圖片進行縮放有,處理圖片時我們經常會用到BitmapFactory類,android系統中讀取位圖Bitmap時分給虛擬機中圖片的堆棧大小隻有8M。
用BitmapFactory解碼一張圖片時,有時也會遇到該錯誤。這往往是由於圖片過大造成的。這時我們需要分配更少的內存空間來存儲。
BitmapFactory.Options.inSampleSize設置恰當的inSampleSize可以使BitmapFactory分配更少的空間以消除該錯誤。inSampleSize的具體含義請參考SDK文檔。Android提供了一種動態計算的

方法,可以去查看源碼,這裏不多講。(當你僅僅只需要縮放一張圖片時可以儘量的保證圖片的質量而犧牲內存空間,如處理的圖片比較頻繁建議犧牲圖像質量而保證你可以處理更多的圖片,opts.inSampleSize 的計算一般都是動態計算比較多,直接給值的靈活性差。

一下一些計算方法給出供大家參考:

       /**
 *  網絡版求解縮放比例法
 * @param options BitmapFactory.Options
 * @param minSideLength 最小顯示區 一般賦值爲 -1
 * @param maxNumOfPixels 顯示區長 * 寬 的值
 * @return
 */
public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}


        /**
*  求縮放大小的比例 自己做比較計算的到的size
* @param opts
* @param newHeight 顯示高
* @param newWidth  顯示寬
* @return
*/
public static int computeSampleSizeSample(BitmapFactory.Options opts, int newHeight, int newWidth){
if(opts.outHeight > newHeight || opts.outWidth > newWidth){
int insamplesizeH = opts.inSampleSize = opts.outHeight / newHeight;   // 壓縮比的設置高壓縮
int insamplesizeW = opts.inSampleSize = opts.outWidth / newWidth;   // 壓縮比的設置寬壓縮
opts.inSampleSize = opts.outHeight / newHeight;   // 壓縮比的設置高壓縮


if(insamplesizeW > insamplesizeH){
opts.inSampleSize = opts.outWidth / newWidth;   // 壓縮比的設置寬壓縮
}
}else{
opts.inSampleSize = opts.outHeight / newHeight;   // 壓縮比的設置 高壓縮 溢出問題
}
return opts.inSampleSize;
}


例如:
     BitmapFactory.Options opts = newBitmapFactory.Options();
    opts.inSampleSize = 4 ;
    Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);
5.Dalvik.VMRuntime類,提供對虛擬機全局,Dalvik的特定功能的接口。
Android爲每個程序分配的對內存可以通過Runtime類的 totalMemory() freeMemory() 兩個方法獲取VM的一些內存信息,對於系統heap內存獲取,可以通過Dalvik.VMRuntime類的

getMinimumHeapSize() 方法獲取最小可用堆內存,同時顯示釋放軟引用可以調用該類的gcSoftReferences() 方法,收集可用內存。
我們還可以強制定義自己軟件的對內存大小,我們使用Dalvik提供的 dalvik.system.VMRuntime類來設置最小堆內存爲例:

private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;

VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //設置最小heap內存爲6MB大小。當然對於內存吃緊來說還可以通過手動干涉GC去處理,我們將在下次提到具體應用。

使用 dalvik.system.VMRuntime類提供的setTargetHeapUtilization方法可以增強程序堆內存的處理效率。當然具體原理我們可以參考開源工程,

 這裏我們僅說下使用方法: 
 private final static float TARGET_HEAP_UTILIZATION = 0.75f;

在程序onCreate時就可以調用VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。

6.緩存,適量使用緩存,不要過量使用,因爲內存有限,能保存路徑地址的就不要存放圖片數據,不經常使用的儘量不要緩存,不用時就清空。(使用完緩存後一定記得將對象賦null,便於虛擬機回收資源,同時不要重複的去new 這些緩存對象。)

7.儘量使用Android 自己一套的機制,因爲android是基於Dalvik而非JVM。

 InputStream is = null;
         try {
         is = new FileInputStream(newFile(picstr));
    
         } catch (FileNotFoundException e) {
        // http://www.cnblogs.com/tankaixiong/
        // }
下面這個方法肯定優於上面這個方法。
 Resources re = mContext.getResources();
         InputStream is =re.openRawResource(picstr);

 8.補充一點一定要將java中對於文件操作的好習慣保持了對於文件流,一定要關閉,且確定不用後對象必須賦nul,資源管理就是從這一點一滴開始的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章