Handler源码解析
一、创建Handler对象
使用handler最简单的方式:直接new一个Handler的对象
Handler handler = new Handler();
所以我们来看看它的构造函数的源码:
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这段代码做了几件事:
1、校验是否可能内存泄漏
2、初始化一个Looper mLooper
3、初始化一个MessageQueue mQueue
我们一件事一件事的看:
1、校验是否存在内存泄漏
Handler的构造函数中首先判断了FIND_POTENTIAL_LEAKS的值,为true时,会获取该对象的运行时类,如果是匿名类,成员类,局部类的时候判断修饰符是否为static,不是则提示可能会造成内存泄漏。
问:为什么匿名类,成员类,局部类的修饰符不是static的时候可能会导致内存泄漏呢?
答:因为,匿名类,成员类,局部类都是内部类,内部类持有外部类的引用,如果Activity销毁了,而Hanlder的任务还没有完成,那么Handler就会持有activity的引用,导致activity无法回收,则导致内存泄漏;静态内部类是外部类的一个静态成员,它不持有内部类的引用,故不会造成内存泄漏
这里我们可以思考为什么非静态类持有外部类的引用?为什么静态类不持有外部类的引用?
问:使用Handler如何避免内存泄漏呢?
答:使用静态内部类的方式
2、初始化初始化一个Looper mLooper
这里获得一个mLooper,如果为空则跑出异常