通常我们使用如下方式获取一个Handler对象
private Handler mHandler1 = new Handler(){
public void handleMessage(Message msg) {
};
};
private Handler mHandler2 = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
细心一点去看,使用第一种方式定义handler对象时,编译器会报如下警告:
This Handler class should be static or leaks might occur
意思是,Handler类必须为静态的,否则有可能造成内存泄漏。
这是为什么呢,事实上MessageQueen中等待处理的消息持有对Handler对象的引用,而上述第一种方式中我们的Hanler类是一个匿名内部类,它持有了所在外部类的引用(不只是匿名内部类,内部类也会引起这个问题)。一旦消息队列里的消息长时间未处理,那么handler对象就一直被持有,它的外部类也一直被持有,导致无法及时CG,内存泄漏就发生了。
那为什么使用static修饰变量时,就可以避免内存泄漏呢?那是因为静态的方法和变量都不属于类本身,不会持有对类的引用,自然也不会出现内存泄漏了,但是这种方式又必须为静态的代码提供额外的内存,程序中大量使用handler时,这种处理到底合理不合理呢?
经过网友的好心提示,特此更正及讲解第一二种方式的区别
第一种方式new出的handler对象是一个匿名内部类,它直接持有外部类的引用,因此系统直接警告不要使用这种方式
第二种方式new出的handler是一个对象,它本身不是匿名内部类,因此没有警告语句,这里需要提一句,它的回调函数确实也是一个匿名的内部类,但这并不表示handler是匿名内部类。当然第二种方式也是存在内存泄漏的风险的,所以想要直接避免类似的问题,我们可以继承handler 编写自己的实现类,详情可以参考篇末的文章。
为什么这个检查语句只关注handler本身呢,下一篇文章里有讲到哦。
匿名内部类的讲解百科就讲的很好,有疑问的朋友可以点开看看内部类
另外,谢谢各位网友的提示和监督,人无完人,若有不对请多多指教,作者也会接纳意见,但是冷嘲热讽的也不说个所以然的就谢绝了,匿名内部类是什么都没搞清楚的请好好学习一下。
关于警告语句的处理其实还有其他方法 可以参考点击打开链接