Android 常見 Memory Leak 緣由及解決辦法總結

背景

在Android開發過程當中,咱們常常碰到的狀況就是在咱們不清楚爲何狀況下,程序忽然出現Crash了。其中有一類日誌相信你們都常常碰到過,這類日誌就是OOM相關的日誌。這類日誌除了咱們知道的Bitmap操做的時候會常常致使,還有一種隱藏的較深的緣由就是內存泄露(Memory Leak)。編輯器

內存泄露產生緣由和影響:

  • 緣由:當一個Object再也不須要的時候,本該被GC回收時,可是由於另外一個正在使用的Object持有它致使不能正常的被回收,本該被回收的對象不能回收,還存留在堆內存中,此時就產生了內存泄露。
  • 影響:Android系統可以爲每一個應用程序分配的內存是有限的,當一個應用程序中產生的內存泄露過多的時候,會不免致使應用程序須要的內存超過限額而致使內存溢出使得應用程序崩潰。

內存泄露的檢測方式

推薦使用 LeakCanary 工具來檢測應用程序是否存在內存泄露。LeakCanary是由 Square 開源的一款輕量級的第三方內存泄漏檢測工具,當檢測到程序中產生內存泄漏時,它將以最直觀的方式告訴咱們哪裏產生了內存泄漏和致使誰泄漏了而不能被回收。工具

如何避免內存泄露

一、合理使用單例模式。

單例的靜態特性使得其生命週期和應用的生命週期同樣長。
如圖,咱們先聲明一個單例對象:

而後在Activity使用的時候,習慣性的傳一個this:

集成了LeakCanary後測試,發現內存泄露了:

解決方案:
通常狀況下,改爲以下圖的寫法就能夠了,由於單例的生命週期和應用的同樣長,這樣就防止了內存泄漏。:

總結:單例模式形成泄漏的緣由是擁有更長生命週期的對象持有短生命週期對象的強引用。測試

二、使用資源時注意資源的關閉

通常狀況下,容易產生內存泄露的資源主要爲:File,Cursor,Stream,Bitmap,BroadcastReceiver等,這些資源在使用時建議及時關閉,不然當這些資源沒有及時回收的時候,內存泄露也就產生了。針對這些資源使用,給以下建議:this

  • BroadcastReceiver 在register以後,須要在適當的時機unregister
  • Cursor、Stream、File 這類資源類型的對象每每會使用一些Cache,因此咱們在不使用的時候,應該及時關閉,以便Cache被及時回收。若是咱們僅僅把它的引用設置爲null,而不去關閉他們,每每會形成內存泄露。通常建議是先close()後置爲null。
  • Bitmap在不使用的時候,調用recycle()方法。目前 Android 2.3版本之後,不須要咱們手動去這樣作的,這裏也就是簡單的交代一下。

三、 合理使用Handler避免內存泄露

在咱們使用Handler的時候,常常看到編輯器提示咱們Handler可能會形成內存泄露,通常在這種狀況下,咱們能夠將Handler獨立出來或者使用靜態內部類,這樣能夠避免內存泄露。
這樣作的緣由是:非靜態內部類會潛在的持有它所屬的外部類的引用,可是靜態內部類是不會的。日誌

四、 合理的使用WeakReference來引用外部類的成員變量

咱們可使用WeakReference來規避好多潛在的內存泄露的問題,可是並不代表WeakReference就是解決內存泄露的金鑰匙。是否使用WeakReference主要取決於對當前對問題的理解,這須要咱們對問題的的建模思想。對象

參考文章:

  1. http://www.jianshu.com/p/e3ac42a2aea2
  2. http://puretech.iteye.com/blog/2008663
相關文章
相關標籤/搜索