我们在写Android程序的时候经常会使用到Handler,最常用的初始化Handler的方式如下:
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
//逻辑处理
}
};
在这样写完之后我不知道大家有没有注意到Android Studio给了我们一个警告提示:
This Handler class should be static or leaks might occur...
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected.
If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no
issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler
declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference
to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references
to members of the outer class using the WeakReference object.
上面这段警告的大致意思就是说:Handler被声明成了内部类,而如果我们又使用了主线程的Looper或者MessageQueue,那么可能会导致外部类也就是Activity无法被垃圾回收器回收而造成内存泄漏。建议是使用静态Handler类,并在外部类初始化WeakReference对象,然后传入到Handler中,然后使用这个WeakReference对象。
用代码来说明就是这样:
private LodingHandler handler = new LodingHandler(new WeakReference<LodingActivity>(this));
static class LodingHandler extends Handler{
WeakReference<LodingActivity> activityWeakReference;
public LodingHandler(WeakReference<LodingActivity> activityWeakReference){
this.activityWeakReference = activityWeakReference;
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
LodingActivity activity = activityWeakReference.get();
if (null != activity){
//逻辑处理
}
}
}
那么造成这个问题的原因是:
由于在Java中非静态匿名内部类将保存对外部类的隐式引用,而静态内部类则不会。安卓框架的工程师 Romain Guy曾说明过他在 Android 代码库中发现了一些内存泄漏,Message 有一个对 Handler 的引用,当它是内部的和非静态的时候,它有一个对外部 this 的引用(例如一个 Activity。) 如果 Message 在队列中长时间存在(例如,在发布延迟消息时非常容易发生这种情况) ,则保留对 Activity 的引用并“泄漏”所有视图和资源。