一個給開發者使用的Android App內存清理、監控工具,能夠獲取當前手機的內存使用比率,可用內存大小,檢查一個APP是否存在內存泄漏。html
而且整理了一些優化內存的方式。android
相似360衛士的 加速球,獲取系統已用內存比率、可用內存大小,一鍵清理。git
能夠用於測試本身開發的Activity、Fragment健壯性,模擬Activity、Fragment被回收的場景,測試本身的程序是否無缺的保存、恢復當前場景。github
好比:打開你開發的某個Activity、Fragment,切到後臺,清理一次內存,在將其切回前臺後,看會不會出現空指針異常,以及程序狀態是否被恢復。數據庫
Android系統中的內存和Linux系統同樣,存在着大量的共享內存。每一個APP佔內存會有私有和公共的兩部分,咱們能夠經過App的Pss值,能夠獲取到這兩部份內存。數據結構
Pss(Proportional Set Size):實際使用的物理內存,即:自身應用佔有的內存+共享內存中比例分配給這個應用的內存。工具
經過改程序,每隔1秒,獲取一次被監控App的Total Pss值。測試
使用某個功能(可能會致使OOM的那些都要試試),查看Pss是否飆升,或者使用過許久都沒有下降。優化
若是使用後飆升而且長時間都降不下來,那就說明確定會致使OOM(對象使用過以後還被引用着未釋放),若是使用以後Total Pss飆升,可是使用過以後能降下來,也可能會致使OOM,咱們仍是須要去一點一點排查是什麼緣由致使的。ui
若是使用後飆升而且長時間都降不下來,咱們就須要使用MAT來進一步分析問題所在。
Android的虛擬機是基於寄存器的Dalvik,它的最大堆大小通常比較小(最低端的設備16M,後來出的設備變成了24M,48M等等),所以咱們所能利用的內存空間是有限的。若是咱們使用內存佔用超過了必定的限額後就會出現OutOfMemory的錯誤。
可能會致使內存溢出的狀況有如下幾種:
若是一個變量爲static變量,它就屬於整個類,而不是類的具體實例,因此static變量的生命週期是特別的長,若是static變量引用了一些資源耗費過多的實例,例如Context,就有內存溢出的危險。
Google開發者博客,給出了一個例子:http://android-developers.blogspot.jp/2009/01/avoiding-memory-leaks.html 專門介紹長時間的引用Context致使內存溢出的狀況。
這種狀況:
靜態的sBackground變量,雖然沒有顯式的持有Context的引用,可是: 當咱們執行view.setBackgroundDrawable(Drawable drawable);以後。 Drawable會將View設置爲一個回調(經過setCallback()方法),因此就會存在這麼一個隱式的引用鏈:Drawable持有View,View持有Context sBackground是靜態的,生命週期特別的長,就會致使了Context的溢出。
解決辦法: 1.不用activity的context 而是用Application的Context; 2.在onDestroy()方法中,解除Activity與Drawable的綁定關係,從而去除Drawable對Activity的引用,使Context可以被回收;
長週期內部類、匿名內部類,如Handler,Thread,AsyncTask等。
HandlerOutOfMemoryActivity所示的是Handler引起的內存溢出。
ThreadOutOfMemoryActivity所示的是Thread引起的內存溢出。
AsyncTaskOutOfMemoryActivity所示的時AsyncTask引起的內存溢出。
通常是由於嘗試加載過大的圖片到內存,或者是內存中已經存在的過多的圖片,從而致使內存溢出。
正常狀況下,若是查詢獲得的數據量較小時不會有內存問題,並且虛擬機可以保證Cusor最終會被釋放掉,若是Cursor的數據量特表大,特別是若是裏面有Blob信息時,應該保證Cursor佔用的內存被及時的釋放掉,而不是等待GC來處理。
若是在某個Activity中使用 Singleton instance = Singleton.getInstance(this);
就會形成該Activity一直被 Singleton
引用着,不能釋放。這時候,正確的作法是使用 getApplicationContext()
來替代 Activity的Context
,這樣就能避免內存泄露。
- 儘可能使用9path
- Adapter要使用convertView
- 各類監聽,廣播等,註冊的同時要記得取消註冊
- 使用完對象要及時銷燬,能使用局部變量的不要使用全局變量,功能用完成後要去掉對他的引用
- 切勿在循環調用的地方去產生對象,好比在getview()裏new OnClicklistener(),這樣的話,拖動的時候會new大量的對象出來。
- 使用Android推薦的數據結構,好比HashMap替換爲SparseArray,避免使用枚舉類型(在Android平臺,枚舉類型的內存消耗是Static常量的的2倍)
- 使用lint工具優化工程
- 字符串拼接使用StringBuilder或者StringBuffer
- 儘可能使用靜態匿名內部類,若是須要對外部類的引用,使用弱引用
- for循環的使用 用 final int size = array.length; for(int i = 0; i< size;i++) 來替代: for(int i =0;i < array.length;i++)
最後。
我整理了一些開發中可能會致使內存溢出的狀況,放在com.cundong.memory.wrong中,而且給出了優化方法,放在com.cundong.memory.right中。