2012-01-25 131 views
13

我見過很多樣本,開發人員在位圖上調用recycle(),然後將其設置爲null。 爲什麼這是必要的,不是垃圾收集器照顧釋放位圖?Android - 位圖和內存管理?

Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
bitmap.recycle(); 
bitmap = null; 

回答

17

加入俱樂部。它有點但不完全。

問題是,在Android的前Honeycomb版本中,位圖的內存是從非託管內存分配的,這會產生各種各樣的問題。它仍然是從位圖對象實現的終結器發佈的。這意味着至少需要2次GC通過才能收集。此外,如果因爲某種原因終結者未能執行 - 你得到了圖片。另一件事是 - 這是真的無從考證 - DDMS不會看到它,同樣沒有MAT

對於Android 3.0的這個已經改變,位圖是在管理字節數組實現,但對於上了年紀的手機...

3

bitmap.recycle();釋放位圖中使用的本地堆。將其設置爲空即可幫助GC快速收集參考。

+3

@aryaxt:請注意,儘管終結器會爲您執行一個「recycle()」,但您自己調用它可以更快地釋放內存,從而使您不太可能用完堆空間。 – CommonsWare

+1

是....還有一點需要注意....您需要確保在回收之前不再使用位圖...否則在嘗試使用回收位圖時會遇到異常。 –

+4

同樣,Android 3.0位圖不再使用本機堆。 –

1

來自http://developer.android.com/reference/android/graphics/Bitmap.html#recycle%28%29的文檔。


釋放與此位圖關聯的本地對象,並清除對像素數據的引用。這不會同步釋放像素數據;它只是允許它被垃圾收集,如果沒有其他引用。位圖被標記爲「死亡」,這意味着如果getPixels()或setPixels()被調用,它將拋出異常,並且不會畫任何東西。這個操作不能顛倒過來,所以只有在你確定沒有進一步的位圖使用時才應該調用它。這是一個高級調用,通常不需要調用,因爲當沒有更多的位圖引用時,普通的GC進程將釋放該內存。


所以它似乎沒有必要打電話。唯一一次我聽說過需要手動將對象設置爲null的情況是,如果它的靜態變量(或者某個不會輕易超出範圍的變量),並且您想強制將其從內存中移出。也許如果你不斷快速分配位圖,可能需要嘗試並強制垃圾收集,但在大多數情況下可能不需要。

+1

根據文檔所有內容看起來都不錯,但是在位圖導致OOM的情況下有很多情況....所以如果你在你的代碼中遇到這個問題,修復它的一般方法是確保我們將位圖設置爲null並從代碼中調用gc ...(是的,我知道這不是最優的,它不能保證gc)...但這是獲得一些回憶的最後手段....你也可以嘗試使用SoftReferences進行位圖緩存 –

+0

我已經將數百個位圖一次加載到內存中,並沒有出現問題。我可以看到這一點的唯一方法是在現代手機上存在的一個問題是,如果您的內存泄露了您的位圖,或者您正在快速分配並丟棄位圖(遠遠超過您可以立即安裝在屏幕上)。 – onit

+0

http://code.google.com/p/android/issues/detail?id=11089檢查羅曼傢伙的迴應.... –