Android雖然會自動管理記憶體,JAVA也有garbage collection (GC )記憶體回收機制。
但是如果程式在一次操作中開啟幾個M的檔案,那麼通常會出現下面的錯誤資訊。
02-04 21:46:08.703: ERROR/dalvikvm-heap(2429): 1920000-byte external allocation too large for this process.
或
02-04 21:52:28.463: ERROR/AndroidRuntime(2429): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
移動終端因為記憶體有限,往往圖片處理經常出現上述的錯誤。
解決方案:
1.明確調用System.gc();
這種記憶體回收會有一定的作用,但是請不要太期待。
2.圖片處理完成後回收記憶體。
請在調用BitMap進行圖片處理後進行記憶體回收。
bitmap.recycle();
這樣會把剛剛用過的圖片佔用的記憶體釋放。
3.圖片處理時指定大小。
下面這個方法處理幾個M的圖片時是必須的。
view plaincopy to clipboardprint?
BitMap getBitpMap(){
ParcelFileDescriptor pfd;
try{
pfd = mCon.getContentResolver().openFileDescriptor(uri, "r");
}catch (IOException ex){
return null;
}
java.io.FileDescriptor fd = pfd.getFileDescriptor();
BitmapFactory.Options options = new BitmapFactory.Options();
//先指定原始大小
options.inSampleSize = 1;
//只進行大小判斷
options.inJustDecodeBounds = true;
//調用此方法得到options得到圖片的大小
BitmapFactory.decodeFileDescriptor(fd, null, options);
//我們的目標是在800pixel的畫面上顯示。
//所以需要調用computeSampleSize得到圖片縮放的比例
options.inSampleSize = computeSampleSize(options, 800);
//OK,我們得到了縮放的比例,現在開始正式讀入BitMap資料
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//根據options參數,減少所需要的記憶體
Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
return sourceBitmap;
}
//這個函數會對圖片的大小進行判斷,並得到合適的縮放比例,比如2即1/2,3即1/3
static int computeSampleSize(BitmapFactory.Options options, int target) {
int w = options.outWidth;
int h = options.outHeight;
int candidateW = w / target;
int candidateH = h / target;
int candidate = Math.max(candidateW, candidateH);
if (candidate == 0)
return 1;
if (candidate > 1) {
if ((w > target) && (w / candidate) < target)
candidate -= 1;
}
if (candidate > 1) {
if ((h > target) && (h / candidate) < target)
candidate -= 1;
}
通過上面的方式解決了,但是這並不是最完美的解決方式。
通過一些瞭解,得知如下:
最佳化Dalvik虛擬機器的堆記憶體配置
對於Android平台來說,其託管層使用的Dalvik Java VM從目前的表現來看還有很多地方可以最佳化處理,比如我們在開發一些大型遊戲或耗資源的應用中可能考慮手動幹涉GC處理,使用 dalvik.system.VMRuntime類提供的setTargetHeapUtilization方法可以增強程式堆記憶體的處理效率。當然具體原理我們可以參考開源工程,這裡我們僅說下使用方法: private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程式onCreate時就可以調用
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。
Android堆記憶體也可自己定義大小
對於一些Android項目,影響效能瓶頸的主要是Android自己記憶體管理機制問題,目前手機廠商對RAM都比較吝嗇,對於軟體的流暢性來說RAM對效能的影響十分敏感,除了 最佳化Dalvik虛擬機器的堆記憶體配置外,我們還可以強制定義自己軟體的對記憶體大小,我們使用Dalvik提供的 dalvik.system.VMRuntime類來設定最小堆記憶體為例:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //設定最小heap記憶體為6MB大小。當然對於記憶體吃緊來說還可以通過手動幹涉GC去處理
if (VERBOSE)
Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w/candidate) + " / " + (h/candidate));
return candidate;
}