1. 原因分析
1.1 内存泄漏实例
首先看一个简单的Handler引发内存泄漏的例子:
public class HandlerActivity extends Activity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Const.NOTIFY_LOCATION_SUC:
boolean isSuc = (Boolean) msg.obj;
doLocation(isSuc);
break;
default:
break;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
mHandler.sendEmptyMessageDelayed(Const.NOTIFY_LOCATION_SUC, 10000);
}
}
1.2 内存泄漏分析
Handler的引用阻止GC回收Activity
在Java中,非静态(匿名)内部类会默认隐性引用外部类对象。
如果外部类是Activity就会造成内存泄漏Handler和Activity的生命周期不一致
就上面的例子而言,当Activity结束后,消息循环中还有延时消息,那么Handler还会一直存在,知道所有消息处理完,但Handler引用了Activity,那么就会阻止Activity被回收,造成内存泄漏。
2. 解决方式
(1)使用显式引用
- 把Handler声明为静态内部类,而静态内部类不会引用外部类对象
- 把Handler声明为静态外部类
(2)在handler中弱引用Activity
public class HandlerActivity extends Activity {
private static final int MSG_START_RECORDING = 0x1001;
private static final int MSG_STOP_RECORDING = 0x1002;
private WorkHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new WorkHandler(this);
}
public void start() {
mHandler.sendMessage(mHandler.obtainMessage(MSG_START_RECORDING));
}
public void stop() {
mHandler.sendMessage(mHandler.obtainMessage(MSG_STOP_RECORDING));
}
private static class WorkHandler extends Handler {
private WeakReference<HandlerActivity> mWeakActivity;
public WorkHandler(HandlerActivity activity) {
super();
mWeakActivity = new WeakReference<HandlerActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity activity = mWeakActivity.get();
switch (msg.what) {
case MSG_START_RECORDING:
activity.handleStartEncoding();
break;
case MSG_STOP_RECORDING:
activity.handleStopEncoding();
break;
}
}
}
private void handleStartEncoding() {
}
private void handleStopEncoding() {
}
}