Handler內(nèi)存泄漏原因
Handler是我們常用的一個(gè)對(duì)象,在之前的文章已經(jīng)分析了Handler的工作機(jī)制,然而,在使用Handler的過程中容易造成內(nèi)存泄漏。常見的場景如下。
場景一
public class MainActivity extends AppCompatActivity {
private CalendarPageView calendar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
}
},10000);
}
}
在Java中在內(nèi)部創(chuàng)建對(duì)象之后會(huì)隱式的持有外部對(duì)象,也就是說new Handler()之后Handler對(duì)象對(duì)Activity就有了一個(gè)持有,那么此時(shí)finish掉Activity的話是沒辦法回收的。這就造成了內(nèi)存泄漏。
場景二
private Handler handler = new Handler(){
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
Activity activity = MainActivity.this;
}
};
在里面Handler不僅僅是隱式的持有,也有顯示的持有Activity,若執(zhí)行延時(shí)操作也會(huì)導(dǎo)致Activity無法被回收。
對(duì)于隱式持有,Handler的postDelayed方法,實(shí)際上是先把Message添加到MessageQueue中,進(jìn)而等待Message的執(zhí)行,所以而Message又是在主線程的Looper中穿件,所以持有鏈接是ActivityThread->Looper->MessageQueue->Message->Handler->Activity
Handler內(nèi)存泄漏解決方案
首先Handler的具體實(shí)現(xiàn)使用靜態(tài)內(nèi)部類的方式。再對(duì)外部的Activity進(jìn)行弱引用。
static class MyHanler extends Handler{
WeakReference<Activity> activity;
public MyHanler(Activity activity) {
this.activity = new WeakReference<Activity>(activity);
}
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
Activity act = activity.get();
if(null == act){
return;
}
}
}
然后再創(chuàng)建Handler,由于Activity是弱引用,這樣當(dāng)Activity結(jié)束之后Handler無法繼續(xù)持有Activity,這樣避免內(nèi)存泄漏。
當(dāng)然若是Handler有延時(shí)操作,那么Handler依然會(huì)存在,如果延時(shí)消息在Activity銷毀之后沒有存在的必要,那么我們可以在Activity銷毀之后刪除Handler的消息。
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}