銜接上篇:
新年過后獻上關于Android內存泄漏的種種總結
(順手留下GitHub鏈接,需要獲取相關面試等內容的可以自己去找)
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)
在Android應用的開發中,為了防止內存溢出,在處理一些占用內存大而且聲明周 期較長的對象時候,可以盡量應用軟引用和弱引用技術。
軟/弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用 的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊 列中。利用這個隊列可以得知被回收的軟/弱引用的對象列表,從而為緩沖器清除已 失效的軟/弱引用。
假設我們的應用會用到大量的默認圖片,比如應用中有默認的頭像,默認游戲圖標 等等,這些圖片很多地方會用到。如果每次都去讀取圖片,由于讀取文件需要硬件 操作,速度較慢,會導致性能較低。所以我們考慮將圖片緩存起來,需要的時候直 接從內存中讀取。但是,由于圖片占用內存空間比較大,緩存很多圖片需要很多的 內存,就可能比較容易發生OutOfMemory異常。這時,我們可以考慮使用軟/弱引 用技術來避免這個問題發生。
以下就是高速緩沖器的雛形: 首先定義一個HashMap,保存軟引用對象。
private Map <String, SoftReference<Bitmap>> imageCache = new Has
hMap <String, SoftReference<Bitmap>> ();
再來定義一個方法,保存Bitmap的軟引用到HashMap
。
使用軟引用以后,在OutOfMemory異常發生之前,這些緩存的圖片資源的內存空間 可以被釋放掉的,從而避免內存達到上限,避免Crash發生。 如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。
如果對于應用的性 能更在意,想盡快回收一些占用內存比較大的對象,則可以使用弱引用。
另外可以根據對象是否經常使用來判斷選擇軟引用還是弱引用。如果該對象可能會 經常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱 引用
ok,繼續回到主題。前面所說的,創建一個靜態Handler內部類,然后對 Handler 持有的對象使用弱引用,這樣在回收時也可以回收 Handler 持有的對象,但是這樣 做雖然避免了 Activity 泄漏,不過 Looper
線程的消息隊列中還是可能會有待處理的 消息,所以我們在 Activity 的 Destroy 時或者 Stop 時應該移除消息隊列 MessageQueue
中的消息。
下面幾個方法都可以移除 Message:
public final void removeCallbacks(Runnable r);
public final void removeCallbacks(Runnable r, Object token);
public final void removeCallbacksAndMessages(Object token);
public final void removeMessages(int what);
public final void removeMessages(int what, Object object);
盡量避免使用 static 成員變量
如果成員變量被聲明為 static,那我們都知道其生命周期將與整個app進程生命 周期一樣。
這會導致一系列問題,如果你的app進程設計上是長駐內存的,那即使app切到 后臺,這部分內存也不會被釋放。按照現在手機app內存管理機制,占內存較 大的后臺進程將優先回收,因為如果此app做過進程互保?;?,那會造成app在 后臺頻繁重啟。當手機安裝了你參與開發的app以后一夜時間手機被消耗空了 電量、流量,你的app不得不被用戶卸載或者靜默。 這里修復的方法是:
不要在類初始時初始化靜態成員??梢钥紤]lazy初始化。 架構設計上要思考是否真 的有必要這樣做,盡量避免。如果架構需要這么設計,那么此對象的生命周期你有 責任管理起來。
override finalize()
2、finalize 方法只會被執行一次,即使對象被復活,如果已經執行過了 finalize 方法,再次被 GC 時也不會再執行了,原因是:
含有 finalize
方法的 object 是在 new 的時候由虛擬機生成了一個 finalize reference
在來引用到該Object的,而在 finalize 方法執行的時候,該 object 所 對應的 finalize Reference
會被釋放掉,即使在這個時候把該 object 復活(即用 強引用引用住該 object ),再第二次被 GC 的時候由于沒有了 finalize reference
與之對應,所以 finalize 方法不會再執行。
3、含有Finalize方法的object需要至少經過兩輪GC才有可能被釋放。
BraodcastReceiver
,ContentObserver
,File,游標 Cursor, Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者注銷,否 則這些資源將不會被回收,造成內存泄漏。比如:
構造 Adapter 時,沒有使用緩存的 convertView
,每次都在創建新的 converView
。這里推薦使用 ViewHolder
。
getApplicationContext
或者 getApplication
,以避免 Activity 被外部長 生命周期的對象引用而泄露。Activity onStop
或者 onDestroy
的時候,取消掉該 Handler
對象的 Message
和 Runnable
.BraodcastReceiver
,ContentObserver
,File,游 標 Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或 者注銷。 刪減了一部分,見諒^_^
(順手留下GitHub鏈接,需要獲取相關面試等內容的可以自己去找)
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。