Monday, November 7, 2011

Memory Leak經驗分享-Drawable篇

之前在網路上找到一段程式碼,
可以輕鬆的在Logcat裡看到目前已使用的記憶體(heap memory)量︰

    Log.i("tag", where+"usedMemory: "+Debug.getNativeHeapSize()/ 1048576L);
 
開發時遇到有好幾個ListView在同一個Activity裡做切換時,
heap memory一直累計,
最後導致OOM(OutOfMemory)

今天總算是解決了這個問題。
從Romain Guy先前的presentation裡了解到︰
Android最直接影響heap memory的元件是︰
1)Bitmap
2)Drawable

所以,如果ListView裡有用到這3種元件的話,
請小心記憶體的使用,
並且要做好記憶體回收的管控。

底下這裡特別為Drawable做一點介紹︰

Romain Guy説Drawable是一個非常有趣的東西。
當我們呼叫它時,
他的背後其實有這層關係︰
當我們今天Activity被onDestroy時,
Drawable被回收了,但⋯

我們發現,
因為Context還在被Drawable的Callback參照(reference),
因此,Context無法被回收。
如果我們又再次開啟Activity,
此時記憶體就會變成︰
因此,造成了記憶體累加,
也就是所謂的Memory Leak。

解決方法就是將Drawable的Callback,
在Activity的onDestroy()中設為null。
    Drawable.setCallback(null);
 
以上是Romain Guy對於Memory Leak的介紹影片中提到的問題,
也剛好解決了手上案子遇到的難題,
在這邊跟遇到此問題的同好分享。

相關文章︰
1.使用MAT(記憶體分析)工具查看Memory Leak
2.何謂Memory Leak
3.記憶體超出OutOfMemoryError
4.Android官方布落格2011/03/24
5.Android官方文件

3 comments:

Ken Yang said...

您好,我想請教,因為我有很多個activity,
每個activity都有background,
因此在做換頁時(startactivity)
一定會調用到heap,
所以我在onPause中時做setCallback的動作,
但是我發現呼叫callback之前的heap size和
之後的heapsize是一樣的耶!?
且一樣會發生crashed的情形

小鰻 said...

其實比較容易造成crash大部份是native memory那部份的memory超量而非heap memory,通常都是資源沒有被釋放掉造成的。
除了參考我前一篇寫的MAT工具使用外,在Google查詢更多老外的使用MAT的方法,會對你現在的程式卡在什麼地方沒有釋放掉而造成crash,會有更多的了解。
一定要多下一點工夫在MAT上面,畢竟這是Google I/O大會上也推薦的方法。

hoyin said...

Thx u.. 一直唔明。。原來call back 係object....