Handler源码解析
- handler的构造函数 和 sendMessage()
//构造函数
public Handler(@Nullable 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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//所有的sendMessage方法最终都是调用sendMessageAtTime()
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
// sendMessageAtTime()则调用的是Handler中的enqueueMessage();
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
从上面的两个方法中有四个重点类Handler,Looper,MessageQueue,Message,另外还有一个在创建Looper中定义的成员变量sThreadLocal;
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
- 那就从MessageQueue中enqueueMessage()开始:
(1)MessageQueue的数据结构:用链表 根据 时间 进行排序 的优先级队列;
(2)enqueueMessage(Message msg, long when)就是把消息加入队列中,至于出列,那是在Looper.loop()方法中调用MessageQueue.next()方法,后面会讲到。
MessageQueue.enqueueMessage():
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
// 对MessageQueue进行加锁
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
// 标记Message正在被执行,以及需要被执行的时间,这里的when是距离1970.1.1的时间
msg.when = when;
Message p = mMessages; //p是MessageQueue的链表头
boolean needWake;
// 判断是否需要唤醒MessageQueue
// 如果有新的队头,同时MessageQueue处于阻塞状态则需要唤醒队列
if (p == null || when == 0 || when < p.when) {
if (p == null || when == 0 || when < p.when) { //这个很简单,不分析,msg加入前队列为空时会走此逻辑
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//死循环比较:压入队列中的msg与队列中消息的时间做比较,并找到插入的位置
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Looper.loop():
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;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) { // 死循环取出message
Message msg = queue.next(); // 可能会阻塞;
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
Printer logging = me.mLogging;
// 回调到我们的handler去处理msg,也就是handleMessage()方法;
msg.target.dispatchMessage(msg);
final long newIdent = Binder.clearCallingIdentity();
// 回收Message
msg.recycleUnchecked();
}
}
MessageQueue.next():
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg; //消息出列
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}
如下的图中的模型:enqueueMessage() 把消息加入,next()取出消息,中间的loop()则负责整个消息链上的动力;
looper.png
- 几个知识点:
(1)一条线程可以有多个Handler;
(2)一条线程只能有一个Looper:那么如何保证只有一个Looper呢(Looper如何与线程进行绑定的)?
在子线程中创建Handler:
new Thread(new Runnable() {
@override
public void run(){
// 这行代码不能少,不然会报错:Can'tcreatehandlerinsidethreadthathasnotcalledLooper.prepare()
Looper.prepare();
mHandler1 = newHandler()
Looper.loop();
}
}).start();
接下来看看 Looper.prepare() 做了哪些操作;
public static void prepare() { // Looper的构造函数是private,不能通过new,只能通过prepare()来创建
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
从以上的代码中得知,Looper.loop()就是做了一些初始化的工作,以及sThreadLocal.set(new Looper(quitAllowed))把新创建的looper设置进去;此时我们可以大胆猜想,保证线程中Looper的唯一性很可能就是 这一步。
public void set(T value) {
// 以下两行代码:将ThreadLocal与线程绑定;
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); // 每条线程都会有一个 ThreadLocalMap
if (map != null)
map.set(this, value); //以ThreadLocal做key,Looper做value;
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
通过set()方法,ThreadLocal和Looper就绑定好了,这里只能说明ThreadLocal和Looper(或者说Thread和Looper)的对应关系以及确立,还不能说明一条线程只能有一个Looper,这里就要看我们的 sThreadLocal 这个变量了:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>() 使用了final修饰,只能是唯一的,保证了sThreadLocal 与 looper的唯一性;此外,在Looper初始化后 进行sThreadLocal.set() 时还要先进行检查是否已经绑定过了。
通过这两点,从而保证了一条线程中只有一个Looper。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) { // 通过唯一的ThreadLocal进行get一下,以确保只存在一个Looper;
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
(3)handler 为什么会造成内存泄漏? --- 持有activity
平时使用Handler时,如下代码所示,是一个内部类,默认会持有外部类的对象;
android.os.Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//这里接受并处理消息}
};
//发送消息
handler.sendMessage(message);
那么真正持有activity的时候是在那里呢?在Handler中的enqueueMessage():
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // 就是这一句,也正因为 msg.target = this,在处理存在众多handler的msg时,才能准确找到目标handler
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
message中包含了handler --> handler持有activity -->处理message时 ---messageQueue--->在延时处理的情下,messageQueue会一直间接持有activity,直到消息处理完成,即使activity调用了onDestroy()。
(4)为什么在主线程可以直接new Handler(),而不需要Looper.prepare():
Launcher --> zygote --> application --> ActivityThread.main()
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
子线程中创建Handler:一定要 Looper.prepare() 和 Looper.loop();
(5)如果在多条线程中使用主线程的handler发送消息时,如何保证线程安全:MessageQueue中入列enqueueMessage()和出列next()方法 都会加锁;
(6)如何创建一个新的Message:Message.obtain();
下一章我们将继续深入分析Handler:
Handler源码深入解析