定義
當一個物件已經不需要再使用了,本應該被回收掉,而另一個正在使用的物件持有他的引用,導致物件不能被回收。因為不能被及時回收的本該被回收的記憶體,就產生了記憶體洩露。如果記憶體洩露太多會導致程式沒有辦法申請記憶體,最後出現記憶體溢位的錯誤。
場景
Android開發中經常出現記憶體洩露的點,
- 使用單例模式
- 使用匿名內部類
- 使用非同步事件處理機制
Handler
- 使用靜態變數
- 資源未關閉
- 設定監聽
- 使用
Asynctask
- 使用
Bitmap
優化
- 當查詢完資料庫之後,及時關閉
Cursor
物件。 - 記得在
Activity
的onPause
方法中呼叫unregisterReceiver()
方法,反註冊廣播。 - 避免
Context
記憶體洩露,比如在4.0.1之前的版本上不要將Drawer
物件置為static
。當一個Drawable
繫結到了View
上,實際上這個View
物件就會成為這個Drawable
的一個CallBack成員變數,靜態的SBackground持有TextView
物件lable
的引用,而lable
只有Activity
的引用,而Activity會持有其他更多物件的引用,sBackground
生命週期要長於Activity
,當螢幕旋轉時,Activity
無法銷燬,這樣就產生了記憶體洩露的問題。 - 儘量不要在
Activity
中使用非靜態內部類,因為非靜態內部類會隱式持有外部類例項的引用,當非靜態內部類的引用的生命週期長於Activity的生命週期時,會導致Activity
無法被GC
正常回收掉。 - 謹慎使用執行緒
Thread
,很多人會犯這樣的錯誤:Java
中的Thread
有一個特點就是他們都是直接被GC Root
所引用,也就是說Dalvik
虛擬機器對所有被啟用狀態的執行緒都是持有強引用 ,導致GC
永遠都無法回收掉這些執行緒物件,除非執行緒被手動停止並置為null
或者使用者直接kill掉程式操作,所以當使用執行緒時,一定要考慮在Activity
退出時,及時將執行緒也停止並釋放掉。 - 使用
Handler
時,要麼放在單獨的類檔案中, 要麼就是使用靜態內部類,因為靜態的內部類不會持有外部類的引用,所以不會導致外部類例項的記憶體洩露
參考資料: Android效能優化篇之記憶體優化--記憶體洩漏 資料