首先我們來看一段代碼
public class AutoActivity extends Activity {
Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto);
}
}
上面這段低嗎沒有什么問題,但是在handler對象創(chuàng)建的時候卻會報警告:This Handler class should be static or leaks might occur意思是:Handler
類應(yīng)該為static類型,否則可能會造成內(nèi)存泄漏沿侈。為什么會造成這種情況呢?這種情況就是由于android的特殊機制造成的:當一個android主線程被創(chuàng)
建的時候纬乍,同時會有一個Looper對象被創(chuàng)建笔时,而這個Looper對象會實現(xiàn)一個MessageQueue(消息隊列),當我們創(chuàng)建一個handler對象時斤寂,而handler的
作用就是放入和取出消息從這個消息隊列中,每當我們通過handler將一個msg放入消息隊列時揪惦,這個msg就會持有一個handler對象的引用遍搞。因此當
Activity被結(jié)束后,這個msg在被取出來之前器腋,這msg會繼續(xù)存活溪猿,但是這個msg持有handler的引用,而handler在Activity中創(chuàng)建纫塌,會持有Activity的引用诊县,
因而當Activity結(jié)束后,Activity對象并不能夠被gc回收措左,因而出現(xiàn)內(nèi)存泄漏依痊。
這個根本原因就是:Activity在被結(jié)束之后,MessageQueue并不會隨之被結(jié)束媳荒,如果這個消息隊列中存在msg抗悍,則導致持有handler的引用驹饺,但是又
由于Activity被結(jié)束了,msg無法被處理缴渊,從而導致永久持有handler對象赏壹,handler永久持有Activity對象,于是發(fā)生內(nèi)存泄漏衔沼。但是為什么為static類型就
會解決這個問題呢蝌借?因為在java中所有非靜態(tài)的對象都會持有當前類的強引用,而靜態(tài)對象則只會持有當前類的弱引用指蚁。聲明為靜態(tài)后菩佑,handler將會持
有一個Activity的弱引用,而弱引用會很容易被gc回收凝化,這樣就能解決Activity結(jié)束后稍坯,gc卻無法回收的情況。(至于為什么強引用不能夠被gc自動回收搓劫,而
弱引用對象為什么會被gc回收瞧哟,可以自行去google)。
所以解決這個警告就有幾種方法:
一:將hanlder對象聲明為靜態(tài)的對象枪向。
二:使用靜態(tài)內(nèi)部類勤揩,通過WeakReference實現(xiàn)對Activity的弱引用。具體實現(xiàn)看以下代碼:
public class AutoActivity extends Activity {
MyHandler handler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto);
}
static class MyHandler extends Handler{
WeakReference<AutoActivity> mactivity;
public MyHandler(AutoActivity activity){
mactivity = new WeakReference<AutoActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 100:
//在這里面處理msg
//通過mactivity.get()獲取Activity的引用(即上下文context)
break;
default:
break;
}
}
}
}