內存泄露的原因是引用還存在,無法及時釋放內存,android的內存泄露主要是activity銷毀不及時。
造成內存泄露主要分為兩個原因
- 內部類持有其外部類的引用
- 外部類持有本類引用,而外部類又比本類生命周期長
內部類
內部類主要有
- 靜態內部類
- 非靜態內部類
因為靜態內部類不持有外部類的引用,不會造成泄露。主要討論非靜態內部類。
舉個栗子
private void testThread(){
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000 * 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
new Runable是個匿名內部類,當activity調用finish()的時候由于線程沒有走完,new runable持有activity的引用,所以activity不會被及時的釋放內存。
在內部類造成內存泄露的情況下最經典的是handler的原因
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
以前喜歡這樣直接在activity new Handler出來,但這樣是有風險的,很大可能造成內存泄露。具體原因和解決方法可以看Android中Handler引起的內存泄露
外部類
在activity里面new一個外部類或者調用外部類方法要傳進activity引用時,外部類的生命周期要比activity長的話都有可能造成內存泄露,極端的例子是在activity中傳進引用獲取單例。
public class Singleton {
private static Singleton instance;
private Context mContext;
private Singleton(Context mContext){
this.mContext = mContext;
}
public static synchronized Singleton getInstance(Context mContext) {
if (instance != null){
instance = new Singleton(mContext);
}
return instance;
}
}
靜態變量的生命周期是貫穿整個應用進程的,所以這樣在activity獲取單例是肯定會造成內存泄露的。