Handler、Looper、MessageQueue、ThreadLocal源码详解及之间的联系
这是第一篇自己分享的源码解读,凡事都有第一步,从现在开始吧!这几个知识点都被网上炒的有点烂了,你要说你没看过他们的源码,你都不好意思说自己做过android。
image.pngHandler解读
1. 构造器
Handler()
Handler(Callback)
Handler(Callback,boolean)
Handler(Looper)
Handler(Looper,Callback)
Handler(Looper,Callback,boolean)
构造器中的几个参数,
Callback:方法 public boolean handleMessage(Message msg);
Looper:所在线程的Looper对象
boolean:是否是异步回调消息默认为false,即:post runnable
在构造其中Handler做了什么呢?我们来看一下
检查潜在的泄漏FIND_POTENTIAL_LEAKS
初始化Looper对象
初始化MessageQueue
初始化Callback
初始化mAsyynchronous
2. 关键方法:
sendMessage(Message msg)
sendMessageDelayed(Message msg, long delayMillis)
sendMessageAtTime(Message msg, long uptimeMillis)
enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
dispatchMessage(Message msg)
postRunnable(Rnnable)
removeCallbacksAndMessages(Object token)
这里主要讲dispatchMessage,
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
mCallback即为构造器中的callback
msg.callback即为runnable
handleMessage(msg)为Handler中的空实现方法
方法的处理逻辑为优先处理Message中的callback,其次处理构造其中的handleMessage回调,最后处理Handler中默认的handleMessage方法
Looper
1、构造器
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
初始化MessageQueue和当前线程
2、关键方法
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//quitAllowed参数为是否允许退出消息循环loop,如消息队列中消息为空,该值设置false,就会进入阻塞状态
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
这两个方法是将Looper对象设置到ThreadLocal中
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
初始化主线程的Lopper对象;
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
。。。
for (;;) {
//该处如果quitAllowed为false就会进入阻塞状态
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
。。。
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked();
}
}
对于Looper的退出方法和quitAllowed有关:
public void quit() {
mQueue.quit(false);
}
这是MessageQueue中的方法
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
。。。
}
ThreadLocal
功能:保证了每一个线程都有自己的对象且唯一,Looper类就是利用了ThreadLocal的特性,保证每个线程只存在一个Looper对象。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
源码中使用ThreadLocalMap进行实现,key为ThreadLocal对象的弱引用,ThreadLocal对象最好使用静态static修饰,可能会造成内存泄漏
原因:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,解决方法每次调用都进行remove方法。
网友评论