1、内存泄漏定义
- 本该回收的对象不能被回收,能然停留在内存中。
2、内存泄漏本质
- 持有引用对象的生命周期大于改引用对象的生命周期。如:一个对象不再使用,另一对象能持有改对象的引用,导致该对象不能被回收。
3、Handler 内存泄漏原因
- 泄漏代码
// 1、匿名内部类 创建 Handler 对象,发送和处理消息(内存泄漏问题)
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
mMessageTv.setText("线程:" + msg.obj);
break;
case 2:
mMessageTv.setText("线程:" + msg.obj);
break;
default:
break;
}
}
};
- 原因:Handler 消息队列还有未处理 / 正在处理的消息时,消息队列中的 Message 持有 Handler 实例引用,Handler 持有 Activity 实例引用,导致 Activity 实例无法被回收,导致内存泄漏。
4、Handler 内存泄漏解决方案
注:
强引用:JVM 不主动回收,显示地将引用赋值为null,JVM在合适的时间就会回收该对象。
软引用:内存不足回收,(图片缓存),描述有用但并不是必需的对象。
弱引用:发生垃圾回收时回收,用来描述非必需对象的。
虚引用:任何时候都可能被垃圾回收器回收。
- 方案一:静态内部类 + 弱引用
private NoLeakHandler mNoLeakHandler;
// handler 内存泄漏( 1 静态内部类+ 2 弱引用 + 3 removeCallbacksAndMessages)
private static class NoLeakHandler extends Handler{
private WeakReference<HandlerActivity> mActivity;
public NoLeakHandler(HandlerActivity activity){
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final HandlerActivity activity = mActivity.get();
if(activity == null || activity.isFinishing()) {
return;
}
switch (msg.what) {
case 1:
activity.mMessageTv.setText("线程:" + msg.obj);
break;
case 2:
activity.mMessageTv.setText("线程:" + msg.obj);
break;
default:
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNoLeakHandler = new NoLeakHandler(this);
}
- 方案二:清空 Handler 消息队列
@Override
protected void onDestroy() {
super.onDestroy();
mNoLeakHandler.removeCallbacksAndMessages(null);
}