標籤:android des style blog http java color 使用
今天發現正在做的項目,時不時的會報錯:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的記憶體溢出)
為什麼會記憶體溢出呢?我以前從未遇見這種情況。後來在網上查了查資料,還是挺多的。
怎麼說呢?因為Android開發基本上是以java語言為基礎,那麼程式是在java虛擬機器上啟動並執行。而虛擬機器不允許單個程式中的Bitmap佔用超過8M的記憶體,從報錯的日誌可以看出:7458832-byte大約就是7M多的樣子,基本吻合上述資料。在我的項目中大量的使用到了各種圖片,因此是因為圖片導致記憶體溢出的的可能性很高。
那麼,下面就提供一下解決方案:
第一種方案:
Android堆記憶體也可自己定義大小 和 最佳化Dalvik虛擬機器的堆記憶體配置(LZ沒試過,不過網上很多人都說可行)。
強制定義自己軟體的對記憶體大小,我們使用Dalvik提供的 dalvik.system.VMRuntime類來設定最小堆記憶體為例:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //設定最小heap記憶體為6MB大小。當然對於記憶體吃緊來說還可以通過手動幹涉GC去處理
第二種方案:
手動的回收記憶體。
範例程式碼如下:bit為Bitmap對象
if (bit != null && !bit.isRecycled()) { bit.recycle(); bit = null; }
System.gc();
bitmap.recycle()方法用於回收該bitmap所佔用的記憶體,用System.gc()調用一下系統的記憶體回收行程。
需要注意的是:回收記憶體要及時,比如說SurfaceView,就應該在onSurfaceDestroyed這個方法中回收。如果Activity使用了bitmap,就可以在onStop或者onDestroy方法中回收等等。
我首先就是用的這種方法,修改後發現bug出現的頻率減小了,但仍然存在。
第三種方案:
既然是圖的問題,那就從圖片下手。就是使圖片體積大小變小。
這也分為兩個方面:
1、解析度不變,圖片大小減小2、解析度改變,圖片減小。(用PS都很容易的)
需要注意的是:不要減小得太小而影響了人眼看上去的美感。
以上三種方案,後兩種較簡單且常用。
另外,因為是Android的圖片導致的記憶體問題,那麼就總結了一下與圖片相關的方法的效能,結果很有收穫啊……(不看不知道,一看嚇一跳)
測試的環境為:筆記本i3處理器,64位win7系統,測試手機為小米2S,測試圖片大小為500KB
比較Drawable與Bitmap佔用記憶體大小
比較BitmapFactory類的decodeResource方法與decodeStream方法的效率
以及最佳化後的BitmapFactory類的decodeResource方法。
下面貼上代碼與運行圖:(每次請只運行一個方法,隱藏另外的三種方法)
public class MainActivity extends Activity { int number = 1000; Drawable[] array; Bitmap bitmap[]; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); testDrawable(); // testBitmap_decodeResource(); // testBitmap_decodeStream(); //testnewBitmap_decodeResource(); } /** * 最佳化後的BitmapFactory類的decodeResource方法 */ private void testnewBitmap_decodeResource() { bitmap = new Bitmap[number]; for (int i = 0; i < number; i++) { Log.i("", "測試第" + (i + 1) + "張圖片"); //壓縮,用於節省BITMAP記憶體空間--解決BUG的關鍵步驟 BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 2;//這個的值壓縮的倍數(2的整數倍),數值越小,壓縮率越小,圖片越清晰 //返回原圖解碼之後的bitmap對象 bitmap[i] = BitmapFactory.decodeResource(getResources(), R.drawable.begin_background, opts); } } /** * BitmapFactory類的decodeStream方法 */ private void testBitmap_decodeStream() { bitmap = new Bitmap[number]; for (int i = 0; i < number; i++) { Log.i("", "測試第" + (i + 1) + "張圖片"); bitmap[i] = BitmapFactory.decodeStream(getResources() .openRawResource(R.drawable.begin_background));// 這裡換了方法 } } /** * BitmapFactory類的decodeResource方法 */ private void testBitmap_decodeResource() { bitmap = new Bitmap[number]; for (int i = 0; i < number; i++) { Log.d("", "測試第" + (i + 1) + "張圖片"); bitmap[i] = BitmapFactory.decodeResource(getResources(), R.drawable.begin_background); } } /** * Drawable的使用 */ private void testDrawable() { array = new BitmapDrawable[number]; for (int i = 0; i < number; i++) { Log.w("", "測試第" + (i + 1) + "張圖片"); array[i] = getResources().getDrawable(R.drawable.begin_background); } }}
首先貼出 Drawable的使用 的運行結果:(順利測試完1000張圖片)
BitmapFactory類的decodeResource方法運行結果:(居然只有11張)
運行最佳化後的BitmapFactory類的decodeResource方法:(最佳化後可達到46張,且opts.inSampleSize = n;N的參數設定得越大可達到的數量越多,但損失了圖片品質)
BitmapFactory類的decodeStream方法:(可達22張圖片)
這下,相信大家對Android中與圖片相關的這幾種方法的效能有直觀的認識了吧。其實,在測試時除了看到數量外,還可以看到已耗用時間上的差距。