android防記憶體洩漏與記憶體優化的方法整理
記憶體洩漏
一、單利洩漏
存在記憶體洩露問題的一些程式碼片段像下面這樣:
public class Util {
private Context mContext;
private static Util sInstance;
private Util(Context context) {
this.mContext = context;
}
public static Util getInstance(Context context) {
if (sInstance == null) {
sInstance = new Util(context);
}
return sInstance;
}
}
假設Activity A 裡使用Util類:
Util.getInstance(this);
程式碼大意就是這樣,這樣寫的問題就是,在Activity A 裡使用Util類,傳入的context 是 actvitiy-context。試想一下,當Activity A 生命週期結束,但Util類裡面卻還存在A的引用 (mContext),這樣Activity A佔用的記憶體就一直不能回收,而A的物件也不會再被使用。本人寫程式碼測試過,在A中呼叫了finish(),A的destroy()方法也被執行了,但其佔用的記憶體,比如說,ImageView佔用的記憶體,還是不能釋放的。
那麼如何解決這個問題呢?在A中,可以用Util.getInstance(getApplicationContext());或Util.getInstance(getApplication()); 代替。
因為Application的生命週期是貫穿整個程式的,所以Util類持有它的引用,也不會造成記憶體洩露問題。
2、資源使用完未關閉
一、動態註冊廣播,一定要在onDestroy 呼叫unregisterReceiver 取消註冊,不然當activity結束後,廣播不被回收,導致記憶體洩漏。
二、io Cursor 流要記得close,一定要在finally去close 防止拋異常沒執行close 。
三、bitmap 使用時要記錄recycle,不注意,很容易出現ANR。
3、Handler造成記憶體洩露,
方法一:通過程式邏輯來進行保護。
1.在關閉Activity的時候停掉你的後臺執行緒。執行緒停掉了,就相當於切斷了Handler和外部連線的線,Activity自然會在合適的時候被回收。
2.如果你的Handler是被delay的Message持有了引用,那麼使用相應的Handler的removeCallbacks()方法,把訊息物件從訊息佇列移除就行了。
方法二:將Handler宣告為靜態類。
4、AsyncTask記憶體洩露
在銷燬當前Activity的時候手動去呼叫AsyncTask的cancle方法,(activity 結束後,AsyncTask會在doInBackground()方法執行完畢之後再結束)
記憶體優化
1、儘量使用StringBuilder,不要用"+"去拼接字串,浪費不必要的記憶體。
2、圖片能壓縮,儘量壓縮。
3、儘量使用池:執行緒池,快取池,okhttp裡面的connectionPool(Socket複用池),okio SegmentPool(buffer複用池)------(可以重複 使用物件,減少記憶體開銷,記憶體拉動,cpu開銷)
4、常用的資料結構優化: 能用SparseArray就不用HashMap.
5、xml層級和view :xml層級最好控制在5層以內,多用ViewStub ,include,merge。