Android 專案中對於記憶體優化的幾個細節點

Merbng發表於2019-03-14

定義

當一個物件已經不需要再使用了,本應該被回收掉,而另一個正在使用的物件持有他的引用,導致物件不能被回收。因為不能被及時回收的本該被回收的記憶體,就產生了記憶體洩露。如果記憶體洩露太多會導致程式沒有辦法申請記憶體,最後出現記憶體溢位的錯誤。

場景

Android開發中經常出現記憶體洩露的點,

  • 使用單例模式
  • 使用匿名內部類
  • 使用非同步事件處理機制Handler
  • 使用靜態變數
  • 資源未關閉
  • 設定監聽
  • 使用Asynctask
  • 使用Bitmap

優化

  • 當查詢完資料庫之後,及時關閉Cursor物件。
  • 記得在ActivityonPause方法中呼叫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效能優化篇之記憶體優化--記憶體洩漏 資料

相關文章