轉載請註明本文出自大苞米的博客(http://blog.csdn.net/a396901990),謝謝支持!java
寫在最前:面試
本文的思路主要借鑑了2014年AnDevCon開發者大會的一個演講PPT,加上把網上搜集的各類內存零散知識點進行彙總、挑選、簡化後整理而成。緩存
因此我將本文定義爲一個工具類的文章,若是你在ANDROID開發中遇到關於內存問題,或者立刻要參加面試,或者就是單純的學習或複習一下內存相關知識,都歡迎閱讀。(本文最後我會盡可能列出所參考的文章)。app
OOM:工具
內存泄露能夠引起不少的問題:性能
1.程序卡頓,響應速度慢(內存佔用高時JVM虛擬機會頻繁觸發GC)學習
2.莫名消失(當你的程序所佔內存越大,它在後臺的時候就越可能被幹掉。反以內存佔用越小,在後臺存在的時間就越長)優化
3.直接崩潰(OutOfMemoryError)spa
ANDROID內存面臨的問題:操作系統
1.有限的堆內存,原始只有16M
2.內存大小消耗等根據設備,操做系統等級,屏幕尺寸的不一樣而不一樣
3.程序不能直接控制
4.支持後臺多任務處理(multitasking)
5.運行在虛擬機之上
5R:
本文主要經過以下的5R方法來對ANDROID內存進行優化:
1.Reckon(計算)
首先須要知道你的app所消耗內存的狀況,知己知彼才能百戰不殆
2.Reduce(減小)
消耗更少的資源
3.Reuse(重用)
當第一次使用完之後,儘可能給其餘的使用
5.Recycle(回收)
回收資源
4.Review(檢查)
回顧檢查你的程序,看看設計或代碼有什麼不合理的地方。
Reckon:
關於內存簡介,和Reckon(內存計算)的內容請看上一篇文章:ANDROID內存優化(大彙總——上)
Reduce :
Reduce的意思就是減小,直接減小內存的使用是最有效的優化方式。
下面來看看有哪些方法能夠減小內存使用:
圖片顯示:
咱們須要根據需求去加載圖片的大小。
例如在列表中僅用於預覽時加載縮略圖(thumbnails )。
只有當用戶點擊具體條目想看詳細信息的時候,這時另啓動一個fragment/activity/對話框等等,去顯示整個圖片
圖片大小:
直接使用ImageView顯示bitmap會佔用較多資源,特別是圖片較大的時候,可能致使崩潰。
使用BitmapFactory.Options設置inSampleSize, 這樣作能夠減小對系統資源的要求。
屬性值inSampleSize表示縮略圖大小爲原始圖片大小的幾分之一,即若是這個值爲2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就爲原始大小的1/4。
圖片像素:
圖片回收:
使用Bitmap事後,就須要及時的調用Bitmap.recycle()方法來釋放Bitmap佔用的內存空間,而不要等Android系統來進行釋放。
下面是釋放Bitmap的示例代碼片斷。
捕獲異常:
通過上面這些優化後還會存在報OOM的風險,因此下面須要一道最後的關卡——捕獲OOM異常:
修改對象引用類型:
引用類型:
引用分爲四種級別,這四種級別由高到低依次爲:強引用>軟引用>弱引用>虛引用。
強引用(strong reference)
如:Object object=new Object(),object就是一個強引用了。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具備強引用的對象來解決內存不足問題。
軟引用(SoftReference)
只有內存不夠時纔回收,經常使用於緩存;當內存達到一個閥值,GC就會去回收它;
弱引用(WeakReference)
弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它 所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。
虛引用(PhantomReference)
"虛引用"顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收。
軟引用和弱引用的應用實例:
注意:對於SoftReference(軟引用)或者WeakReference(弱引用)的Bitmap緩存方案,如今已經不推薦使用了。自Android2.3版本(API Level 9)開始,垃圾回收器更着重於對軟/弱引用的回收,因此下面的內容能夠選擇忽略。
在Android應用的開發中,爲了防止內存溢出,在處理一些佔用內存大並且聲明週期較長的對象時候,能夠儘可能應用軟引用和弱引用技術。
下面以使用軟引用爲例來詳細說明(弱引用的使用方式與軟引用是相似的):
假設咱們的應用會用到大量的默認圖片,並且這些圖片不少地方會用到。若是每次都去讀取圖片,因爲讀取文件須要硬件操做,速度較慢,會致使性能較低。因此咱們考慮將圖片緩存起來,須要的時候直接從內存中讀取。可是,因爲圖片佔用內存空間比較大,緩存不少圖片須要不少的內存,就可能比較容易發生OutOfMemory異常。這時,咱們能夠考慮使用軟引用技術來避免這個問題發生。
首先定義一個HashMap,保存軟引用對象。
須要注意的是,在垃圾回收器對這個Java對象回收前,SoftReference類所提供的get方法會返回Java對象的強引用,一旦垃圾線程回收該Java對象以後,get方法將返回null。因此在獲取軟引用對象的代碼中,必定要判斷是否爲null,以避免出現NullPointerException異常致使應用崩潰。
到底何時使用軟引用,何時使用弱引用呢?
我的認爲,若是隻是想避免OutOfMemory異常的發生,則可使用軟引用。若是對於應用的性能更在乎,想盡快回收一些佔用內存比較大的對象,則可使用弱引用。
還有就是能夠根據對象是否常用來判斷。若是該對象可能會常用的,就儘可能用軟引用。若是該對象不被使用的可能性更大些,就能夠用弱引用。
另外,和弱引用功能相似的是WeakHashMap。WeakHashMap對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的回收,回收之後,其條目從映射中有效地移除。WeakHashMap使用ReferenceQueue實現的這種機制。
其餘小tips: