2011-09-03 60 views
4

我已閱讀100篇關於OOM問題的文章。大多數是關於大型位圖的。我正在做一個地圖應用程序,我們下載256x256天氣疊加圖塊。大多數都是完全透明和非常小的。我剛剛得到的,這是442個字節長的位圖流的碰撞,同時呼籲BitmapFactory.decodeByteArray(....).Android - BitmapFactory.decodeByteArray - OutOfMemoryError(OOM)

的異常狀態:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=9415KB, Allocated=5192KB, Bitmap Size=23671KB) 

的代碼是:

protected Bitmap retrieveImageData() throws IOException { 
    URL url = new URL(imageUrl); 
    InputStream in = null; 
    OutputStream out = null; 
    HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 

    // determine the image size and allocate a buffer 
    int fileSize = connection.getContentLength(); 
    if (fileSize < 0) { 
     return null; 
    } 
    byte[] imageData = new byte[fileSize]; 

    // download the file 
    //Log.d(LOG_TAG, "fetching image " + imageUrl + " (" + fileSize + ")"); 
    BufferedInputStream istream = new BufferedInputStream(connection.getInputStream()); 
    int bytesRead = 0; 
    int offset = 0; 
    while (bytesRead != -1 && offset < fileSize) { 
     bytesRead = istream.read(imageData, offset, fileSize - offset); 
     offset += bytesRead; 
    } 

    // clean up 
    istream.close(); 
    connection.disconnect(); 
    Bitmap bitmap = null; 
    try { 
     bitmap = BitmapFactory.decodeByteArray(imageData, 0, bytesRead); 
    } catch (OutOfMemoryError e) { 
     Log.e("Map", "Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage()); 
     System.gc(); 
    } 
    return bitmap; 

} 

這是我在看調試器:

bytesRead = 442 

所以位圖數據是442字節。爲什麼它會試圖創建一個23671KB位圖並耗盡內存?

+0

事情需要注意的是,一些OOM並不必然導致通過觸發錯誤的頁面。有時候,OOM是由以前的活動/錯誤累積而觸發的,這些活動/錯誤是由位圖操作偶然觸發的。我們應該將應用視爲一個整體,而不是觸發OOM的地方。最近的一個問題,我剛剛回答說明了這個場景http://stackoverflow.com/questions/7136198/android-many-outofmemoryerror-exceptions-only-on-single-activity-with-mapview/7154643#7154643其中OOM是不一定是由拋出該錯誤的活動引起的。 – momo

+0

在這個問題上已經有很多關於這個問題的答案,這裏是適合你的解決方案之一。 [內存超過](http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966)**更新:**另一個不錯的答案是在這裏,[內存泄漏]( HTTP://友的解決方案。blogspot.com/2010/08/how-to-if-you-want-to-create-and.html) –

回答

2

我遇到過這樣的問題。 Android使用位圖虛擬機,它非常小。確保你通過bmp.recycle處置你的位圖。後來的Android版本有更多的Bitmap虛擬機,但是我一直在處理的版本有20MB的限制。

+0

我盡我所能地做了很多。這是繪製約12-18這些小的位圖。最大的是大約10K。所以我已經儘可能地瘦了。它是442個字節,正在擴展到20 + MB。這是在Android 2.3 –

+0

民間還這是一個例程來緩存平鋪圖像繪圖在一個MapView。我無法回收位圖或地圖上的繪製例程會崩潰。 –

0

這可能工作。縮小位圖以降低質量。我不確定,但這可能會複製內存中的圖像,但可能很容易值得一試。

  Bitmap image; 
    image = BitmapFactory.decodeByteArray(data, 0, data.length); 
    Bitmap mutableBitmap = image.copy(Bitmap.Config.ARGB_4444, true); 
    Canvas canvas = new Canvas(mutableBitmap); 

我在舊的答案下面我不認爲會工作流。

   Options options = new BitmapFactory.Options(); 
     Options options2 = new BitmapFactory.Options(); 
     Options options3 = new BitmapFactory.Options(); 

     options.inPreferredConfig = Bitmap.Config.ARGB_8888;///////includes alpha 
     options2.inPreferredConfig = Bitmap.Config.RGB_565 ;///////no alpha 
     options3.inPreferredConfig = Bitmap.Config.ARGB_4444 ;/////alpha lesser quality 

     image=BitmapFactory.decodeResource(getResources(),R.drawable.imagename,options); 
     image=Bitmap.createScaledBitmap(image, widthx,height, true); 
+0

https://www.youtube.com/watch?v=1WqcEHXRWpM Google剛剛發佈了一個解釋pixelformats的視頻,如果有人幫助它! –

0

這聽起來像你已經做了關於這個問題的一些閱讀,所以我就饒你的標準',這是你如何解碼位圖的意見..

它跳出了我你可能會堅持引用舊的位圖(也許磁貼離開了屏幕,但是你仍然在某個數組中引用數組,因此它不會被垃圾收集?)。這在過去非常糟糕 - 內存泄漏難以調試。

有很大的Google I/O video over here真的幫助我,當我有類似的問題。大概一個小時,但是幾天之後會有希望爲你節省。 它涵蓋了諸如:

  1. 創建堆轉儲
  2. 堆的使用情況在DDMS
  3. 使用MAT比較/分析堆轉儲