上一節(jié)已經介紹了內存泄漏與引用的關系梯醒,那么這一節(jié)強化一下雹食,看看匿名類跟內存泄漏和引用又存在著什么樣的關系呢澎粟。
匿名類定義
在實際的項目中看到一個很奇怪的現象应闯,Java可以直接new一個接口纤控,然后在new里面粗暴的加入實現代碼,向下面這樣:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(this.getClass());
}
};
runnable.run();
匿名類相當于在定義類的同時再新建這個類的實例
知識點
匿名類也持有著外部類的強引用碉纺。
案例1_匿名AsyncTsk
當你在Activity中定義了匿名的AsyncTsk嚼黔,當異步任務在后臺執(zhí)行耗時任務期間,Activity不幸被銷毀了(用戶退出惜辑,系統(tǒng)回收)唬涧,這個被AsyncTask持有的Activity實例就不會被垃圾回收器回收,直到異步任務結束盛撑。
我們來看如下代碼:
//創(chuàng)建匿名類
void startAsyncTask() {
new AsyncTask<Void, Void, Void>() {
@Override protected Void doInBackground(Void... params) {
while(true);
}
}.execute();
}
//匿名類使用
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
startAsyncTask();
}
});
如上代碼中匿名類AsyncTask執(zhí)行期間碎节,所有持有的引用Activity被銷毀,那么這個activity實例就無法被垃圾回收器回收抵卫,直到異步任務結束狮荔。
案例2_匿名Handler
同樣道理,定義匿名的Runnable介粘,用匿名類Handler執(zhí)行殖氏。Runnable內部類會持有外部類的隱式強引用,被傳遞到Handler的消息隊列MessageQueue中姻采,在Message消息沒有被處理之前雅采,Activity實例不會被銷毀了,于是導致內存泄漏慨亲。
//創(chuàng)建匿名類
void createHandler() {
new Handler() {
@Override public void handleMessage(Message message) {
super.handleMessage(message);
}
}.postDelayed(new Runnable() {
@Override public void run() {
while(true);
}
}, Long.MAX_VALUE >> 1);
}
//匿名類使用
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
createHandler();
}
});
案例3_匿名Thread
定義匿名的Thread未結束之前婚瓜,Activity實例不會被銷毀,也會導致內存泄漏刑棵。
//創(chuàng)建匿名類
void spawnThread() {
new Thread() {
@Override public void run() {
while(true);
}
}.start();
}
//匿名類使用
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
spawnThread();
}
});
案例4_匿名TimerTask
定義匿名的TimerTask未結束之前巴刻,Activity實例不會被銷毀,也會導致內存泄漏蛉签。
//創(chuàng)建匿名類
void scheduleTimer() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
while(true);
}
}, Long.MAX_VALUE >> 1);
}
//匿名類使用
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
scheduleTimer();
}
});
總結
看了上面4個例子胡陪,我們來總結一下:只要是匿名類的實例,不管是不是在工作線程中碍舍,都會持有外部類(Activity)的強引用柠座,導致內存泄漏。
上一節(jié):Android內存泄漏(一):引用
下一節(jié):Android內存泄漏(三):單例