標籤:
常見記憶體泄露原因
Context對象泄漏
1、如果一個類持有Context對象的強引用,就需要檢查其生存周期是否比Context對象更長。否則就可能發生Context泄漏。
2、View持有其建立所在Context對象的引用,如果將View對象傳遞給其它生存周期比View所在Context更長的強引用,就可能會引起記憶體流失。
例如View#setTag(int, Object)的記憶體流失https://code.google.com/p/android/issues/detail?id=18273
3、把Context對象賦給static變數。
避免Context對象泄漏Checklist
1、檢查所有持有對Context對象強引用的對象的生命週期是否超出其所持有的Context對象的生命週期。
2、檢查有沒有把View傳出到View所在Context之外的地方,如果有的話就需要檢查生命週期。
3、工具類中最好不要有Context成員變數,盡量在調用函數時直接通過調用參數傳入。如果必須有Context成員變數時,可以考慮使用WeakReference來引用Context對象。
4、View持有其建立所在Context對象的引用,如果將View對象傳遞給其它生存周期比View所在Context更長的強引用,就可能會引起記憶體流失。
5、 檢查把Context或者View對象賦給static變數的地方,看是否有Context泄漏。
6、檢查所有把View放入容器類的地方(特別是static容器類),看是否有記憶體流失。7、使用WeakHashMap也需要注意有沒有value-key的引用。
7、盡量使用ApplicationContext。
Handler對象泄漏
1、發送到Handler的Message實際上是加入到了主線程的訊息佇列等待處理,每一個Message持有其目標Handler的強引用。
如我們通常使用的匿名內部類Handler
HandlermHandler = new Handler() { @Override public voidhandleMessage(Message msg) { mImageView.setImageBitmap(mBitmap); }}
上面是一段簡單的Handler的使用。當使用內部類(包括匿名類)來建立Handler的時候,Handler對象會隱式地持有一個外部類對象 (通常是一個Activity)的引用,因為View會依附著一個Activity。而Handler通常會伴隨著一個耗時的後台線程(例如從網路拉取圖 片)一起出現,這個後台線程在任務執行完畢(例片下載完 畢)之後,通過訊息機制通知Handler,然後Handler把圖片更新到介面。然而,如果使用者在網路請求過程中關閉了Activity,正常情況 下,Activity不再被使用,它就有可能在GC檢查時被回收掉,但由於這時線程尚未執行完,而該線程持有Handler的引用(不然它怎麼發訊息給 Handler?),這個Handler又持有Activity的引用,就導致該Activity無法被回收(即記憶體泄露),直到網路請求結束(例片 下載完畢)。另外,如果你執行了Handler的postDelayed()方法,該方法會將你的Handler裝入一個Message,並把這條 Message推到MessageQueue中,那麼在你設定的delay到達之前,會有一條MessageQueue -> Message -> Handler -> Activity的鏈,導致你的Activity被持有引用而無法被回收。
當然,應為是Handler對外部持有引用的原因,我們就可以將Activity設定為一個弱引用,在不必要的時候,不再執行內部方法。
import android.app.Activity;importandroid.content.Context;importandroid.os.Handler;importandroid.os.Message; importjava.lang.ref.WeakReference; publicclass WeakRefHandler extends Handler{ WeakReference<context> mWeakContext; public WeakRefHandler(Context context) { mWeakContext = newWeakReference<context>(context); } @Override public void handleMessage(Message msg) { if((mWeakContext.get() instanceofActivity )&& ((Activity)mWeakContext.get()).isFinishing()) return ; if(mWeakContext==null){ return ; } super.handleMessage(msg); }}
android 記憶體最佳化一