Handler为什么会内存泄漏?
内部类持有了外部类的引用。
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
MainActivity.this.click();
//click();
}
};
public void click(){
...
}
就像上面的代码,Handler的内部类中的handleMessage中可以调用外面的click()方法,至于为什么可以调用呢?click()方法的写法上来说是省略了前面的 MainActivity.this. ,然后虚拟机给默认添加了,这就说明,在这个内部类里面,它默认的持有了这个变量,也恰恰是因为它持有了这个变量,它才能可以调用外面的方法。
假如说MainActivity执行了onDestory()方法,这个MainActivity会被释放吗?并不会,因为Java虚拟机中有一个可达性分析,Java 虚拟机就认为,这个MainActivity由于被Handler使用,所以它不能被释放,这个Activity被内部类持有后,只要内部类不被释放,他就不能被释放。
为什么其他内部类没有这个问题?
在RecycleView中,也有一个内部类叫做ViewHolder,它并没有内存泄漏,而偏偏Handler有内存泄漏呢?
有没有记得Handler中有一个方法叫做 sendMessageDelayed()。这个Delayed方法可以是2秒后执行,可以是1分钟之后执行,
因为我们的消息被放在了消息队列里面,如果这个消息要在1分钟之后才能执行,那么这个消息会一直被MessageQueue持有着,这个消息就被一直放在这个队列里面。
这个消息一直放在队列里会带来什么样的影响?
还有handler.sendMessage -> messageQueue.enqueueMessage -> messageQueue添加消息,再到 Looper -> loop() -> messageQueue -> next -> dispatchMessage -> handler.handleMessage 处理消息,它是如何做到是同一个handle对象的?
来看到Looper处理消息的时候会干些什么事情,源码在Looper.loop()里面。
他先从MessageQueue中取出一个消息。
Message msg = queue.next(); // might block
然后又执行了dispatchMessage。
msg.target.dispatchMessage(msg);
注意到没有,他这里是根据target来调用的方法,我们再来看看这个target是什么?(Message.java)
/*package*/ Handler target;
target其实就是一个handler,那target在哪里赋值的?我们回到Handle.java来看调用时候。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在enqueueMessage之前,把this赋值给了target。
这就说明,Message持有了一个Handler,然而,这个Handler又持有了外部类的this。
这就造成,这个Message在还没有处理完成之前,他一直都会处在队列中间,如果这个消息要1分钟之后才能执行,所以至少要等消息处理完之后,才能够销毁这个Message,销毁Message之后才会销毁Handler,销毁Handler之后才会销毁this。所以,这个时候,就是内存泄漏。
总的来说,就是MessageQueue持有了Message,Message持有了Handler,Handler持有了Activity,只是调用了这个Activity的onDestory()并没有用,因为MessageQueue没有释放Message。
回到正题,为什么其他的内部类没有这个问题呢?
所有的内部类都会持有外部类对象,但其他内部类在持有外部类对象的时候没有什么耗时的操作,也没有另外一个东西去持有这个内部类。
如何解决Handler内存泄漏的问题(主线程)?
常用的方法有软引用,static等。
软引用:https://blog.youkuaiyun.com/yichen97/article/details/91488300
static :https://blog.youkuaiyun.com/yichen97/article/details/99086896