会使用Handler之后如何完美的使用Handler成了我们考虑的重点
内存泄漏
JVM的垃圾回收机制相信很多人有所了解,确定一个对象是不是垃圾主要有两种方式:
- 引用计数法:判断是否有引用指向该对象(难以解决两个垃圾对象循环依赖的问题)
- 可达性分析:通过遍历Roots集合,判断对象是否有用
内存泄漏指的是一个对象已经不在使用需要GC回收,但是有一个活跃对象持有该对象的引用导致GC无法回收该对象
Handler引用关系
Handler -> OutClass
class MainActivity {
private Handler handler = new Handler() {
@override
public void handleMessage(Message msg) { //dosomethine }
}
}
这种匿名内部类的方式创建的handler对象会持有外部类的引用,只有静态内部类默认不会持有外部类引用
未处理\正在处理的Message -> Handler
还记得消息分发是根据什么来的吗?Message有一个属性target,分发消息时调用msg.target.dispatchMessage(msg)方法,而这个target属性就是Handler,所以Handler中没有处理的消息会持有Handler的引用
最终引用关系:未处理\正在处理的Message -> Handler -> OutClass
Handler的内存泄漏
原因:1.存在上述引用关系 2.OutClass生命周期 < Handler
解决:破坏其中一个条件即可
破坏引用关系:静态内部类 + 弱引用
class MainActivity {
private Handler handler = new MyHandler(this);
static class MyHandler extends Handler {
private WeekReference<Activity> reference;
public MyHandler(Activity activity) {
使用弱引用持有外部类实例
reference = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(msg) { ... }
}
}
现在的引用关系是怎样的呢?
未处理\正在处理的Message -> Handler ···> OutClass
弱引用的对象生命周期非常短,只要发生垃圾回收该对象就会被回收,不存在内存泄漏
当外部类销毁时清空Handler内的消息
class MainActivity {
private Handler handler = new Handler() {
@Override
public void handleMessage(msg) { ... }
}
@Override
protected void onDestory() {
super.onDestory();
外部类被销毁时,清空Handler中所有消息
handler.removeCallbacksAndMessages(null);
}
}
此时引用关系: Handler -> OutClass
为了防止消息未处理的情况,建议使用静态内部类 + 弱引用的方式避免Handler的内存泄漏