內存泄露
產生的原因:一個長生命周期的對象持有一個短生命周期對象的引用
通俗講就是該回收的對象,因為引用問題沒有被回收,最終會產生OOM
內存抖動
內存頻繁的分配與回收,(分配速度大于回收速度時)最終會產生OOM
使用工具分析內存泄露和抖動
常用的內存分析的工具:
Android Profiler
MAT
DDMS
top/procrank
meinfo
Procstats
Finder-Activity
LeakCanary
LeakInspector
工具很多,掌握原理方法,工具隨便找兩個能用就行,這里就不多做介紹了。
優化內存的良好編碼習慣
1.不要使用比需求更占空間的基本數據類型
2.循環盡量用foreach,少用iterator, 自動裝箱盡量少用
3.數據結構與算法的解度處理
數組,鏈表,棧,樹,圖。。。。。。
數據量千級以內可以使用 Sparse數組(key為整數),ArrayMap(key為對象),性能不如HashMap但節約內存
4.枚舉優化
每一個枚舉值都是一個單例對象,在使用它時會增加額外的內存消耗,所以枚舉相比與 Integer 和 String 會占用更多的內存,較多的使用 Enum 會增加 DEX 文件的大小,會造成運行時更多的IO開銷,使我們的應用需要更多的空間,特別是分dex多的大型APP,枚舉的初始化很容易導致ANR
5.static staticfinal的問題:
static會由編譯器調用clinit方法進行初始化
static final不需要進行初始化工作,打包在dex文件中可以直接調用,并不會在類初始化申請內存
所以基本數據類型的成員,可以全寫成static final
6.字符串的連接盡量少用加號(+)
7.重復申請內存的問題
同一個方法多次調用,如遞歸函數 ,回調函數中new對象,讀流直接在循環中new對象等
不要在onMeause() onLayout() onDraw() 中去刷新UI(requestLayout)
8.避免GC回收將來要重用的對象
內存設計模式對象池+LRU算法
9.Activity組件泄漏
非業務需要不要把activity的上下文做參數傳遞,可以傳遞application的上下文
和Activity有關聯的對象寫成static 如private static Button btn; private static Drawable drawable
非靜態內部類和匿名內部內會持有activity引用
單例模式持有activity引用
handler.postDelayed()問題如果開啟的線程需要傳入參數,用弱引接收可解決問題
handler記得清除removeCallbacksAndMessages(null)
10.盡量使用IntentService,而不是Service