如何避免OOM

1、減少對象的內存佔用html

1)使用更加輕量的數據結構

例如,咱們能夠考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構。android

ArrayMap和HashMap主要不一樣之處在於:數據庫

一、存儲方式不一樣:ArrayMap內部使用兩個數組,一個存HashCode,一個存鍵值對對象。HashMap內部是Entry對象。數組

二、擴容方式不一樣:上面HashMap源碼分析這篇文章說過了,HashMap初始大小是16,達到滿容量的0.75時,要擴容,每次都是上次容量的2倍。緩存

 

ArrayMap用的是copy數據,因此效率相對要高。數據結構

 

最後說說使用場景,若是存儲數量在千級如下,能夠考慮用ArrayMap代替HashMap,但要注意的是,ArrayMap要比HashMap慢。Android裏的Bundle內部就是ArrayMap,因此你們能夠自行考慮使用。函數

2)避免在Android裏面使用Enum

3)減少Bitmap對象的內存佔用

4)使用更小的圖片

2、內存對象的重複利用oop

 

1)複用系統自帶的資源

2)注意在ListView/GridView等出現大量重複子組件的視圖裏對ConvertView的複用

4)避免在onDraw方法裏面執行對象的建立源碼分析

相似onDraw等頻繁調用的方法,必定須要注意避免在這裏作建立對象的操做,由於他會迅速增長內存的使用,並且很容易引發頻繁的gc,甚至是內存抖動。性能

5)StringBuilder

在有些時候,代碼中會須要使用到大量的字符串拼接的操做,這種時候有必要考慮使用StringBuilder來替代頻繁的「+」。

避免對象的內存泄露

1)注意Activity的泄漏

內存對象的泄漏,會致使一些再也不使用的對象沒法及時釋放,這樣一方面佔用了寶貴的內存空間,很容易致使後續須要分配內存的時候,空閒空間不足而出現OOM。顯然,這還使得每級Generation的內存區域可用空間變小,GC就會更容易被觸發,容易出現內存抖動,從而引發性能問題。

一般來講,Activity的泄漏是內存泄漏裏面最嚴重的問題,它佔用的內存多,影響面廣,咱們須要特別注意如下兩種狀況致使的Activity泄漏: 

  • 內部類引用致使Activity的泄漏

最典型的場景是Handler致使的Activity泄漏,若是Handler中有延遲的任務或者是等待執行的任務隊列過長,都有可能由於Handler繼續執行而致使Activity發生泄漏。此時的引用關係鏈是Looper -> MessageQueue -> Message -> Handler -> Activity。爲了解決這個問題,能夠在UI退出以前,執行remove Handler消息隊列中的消息與runnable對象。或者是使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關係的目的。

  • Activity Context被傳遞到其餘實例中,這可能致使自身被引用而發生泄漏。

內部類引發的泄漏不只僅會發生在Activity上,其餘任何內部類出現的地方,都須要特別留意!咱們能夠考慮儘可能使用static類型的內部類,同時使用WeakReference的機制來避免由於互相引用而出現的泄露。

2)考慮使用Application Context而不是Activity Context

對於大部分非必須使用Activity Context的狀況(Dialog的Context就必須是Activity Context),咱們均可以考慮使用Application Context而不是Activity的Context,這樣能夠避免不經意的Activity泄露。

3)注意臨時Bitmap對象的及時回收

雖然在大多數狀況下,咱們會對Bitmap增長緩存機制,可是在某些時候,部分Bitmap是須要及時回收的。例如臨時建立的某個相對比較大的bitmap對象,在通過變換獲得新的bitmap對象以後,應該儘快回收原始的bitmap,這樣可以更快釋放原始bitmap所佔用的空間。

須要特別留意的是Bitmap類裏面提供的createBitmap()方法,如圖所示:

  

這個函數返回的bitmap有可能和source bitmap是同一個,在回收的時候,須要特別檢查source bitmap與return bitmap的引用是否相同,只有在不等的狀況下,纔可以執行source bitmap的recycle方法。

4)注意監聽器的註銷

在Android程序裏面存在不少須要register與unregister的監聽器,咱們須要確保在合適的時候及時unregister那些監聽器。本身手動add的listener,須要記得及時remove這個listener。

5)注意緩存容器中的對象泄漏

有時候,咱們爲了提升對象的複用性把某些對象放到緩存容器中,但是若是這些對象沒有及時從容器中清除,也是有可能致使內存泄漏的。例如,針對2.3的系統,若是把drawable添加到緩存容器,由於drawable與View的強應用,很容易致使activity發生泄漏。而從4.0開始,就不存在這個問題。解決這個問題,須要對2.3系統上的緩存drawable作特殊封裝,處理引用解綁的問題,避免泄漏的狀況。

6)注意WebView的泄漏

Android中的WebView存在很大的兼容性問題,不只僅是Android系統版本的不一樣對WebView產生很大的差別,另外不一樣的廠商出貨的ROM裏面WebView也存在着很大的差別。更嚴重的是標準的WebView存在內存泄露的問題,因此一般根治這個問題的辦法是爲WebView開啓另一個進程,經過AIDL與主進程進行通訊,WebView所在的進程能夠根據業務的須要選擇合適的時機進行銷燬,從而達到內存的完整釋放。

7)注意Cursor對象是否及時關閉

在程序中咱們常常會進行查詢數據庫的操做,但時常會存在不當心使用Cursor以後沒有及時關閉的狀況。這些Cursor的泄露,反覆屢次出現的話會對內存管理產生很大的負面影響,咱們須要謹記對Cursor對象的及時關閉。

 

參考鏈接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html

相關文章
相關標籤/搜索