android基础 Handler源码解析
1.发送消息
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
- 发送消息最终都会调用sendMessageDelayed() -> sendMessageAtTime()。
- post(Runnable)会调用getPostMessage(r),构建一个Message对象,把Runable设置为msg的 callback。(在handler处理消息时会用到msg.callback)
- sendMessageAtTime()的第二个参数为消息执行的时间,SystemClock.uptimeMillis() + delayMillis 为系统启动时间+delatTime。当手动修改系统时间后,Handler消息处理不会出现异常。
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
......
return enqueueMessage(queue, msg, uptimeMillis);
}
```
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//--1
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//--2
return queue.enqueueMessage(msg, uptimeMillis);
}
- 给Message设置target为当前Handler对象。
- 将msg放入mQueue中,mQueue是在Handler()的构造方法中初始化,获取的是mLooper.mQueue,具体类型为MessageQueue
boolean enqueueMessage(Message msg, long when) {
//--1
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
......
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//--2
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
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;
}
- 判断message.target 如果为空,则抛出IllegalArgumentException异常,通过Handler sendMessgae 都会把当前handler对象设置为message的target。
- 通过MessageQueue.postSyncBarrier()可以发送一个target为空的同步消息,称之为同步屏障。用于阻隔所有同步消息的执行。在ViewRootImpl的scheduleTraversal()中就会发出一个同步屏障,用于保证ui绘制的优先执行 3.根据Message执行时间排序,把先执行的Message放在队列前边
2.启动消息循环
public static void 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));
}
```
public static void loop() {
......
}
ThreadLocal.java
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
- 调用Loope.prepare() 和Looper.loop()即可在一个Thread中启动启动消息循环
- 每个Thread只有一个Looper和一个MessageQueue,可以有多个Handler。保证每个线程只有一个Looper和MessageQueue是由ThreadLocal机制实现。在preapre()中,new了一个Looper设置给了sThreadLocal对象,可以看到,最终是以threadLocal为key,Looper为value,存储在了Thread的成员变量threadLocals中。
3.消息循环
Looper.java
public static void loop() {
......
me.mInLoop = true;
final MessageQueue queue = me.mQueue;
......
boolean slowDeliveryDetected = false;
//--1
for (;;) {
//--2
Message msg = queue.next();// might block
//--3
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
......
//--4
msg.target.dispatchMessage(msg)
......
msg.recycleUnchecked();
}
}
- 在loop()中,开启了一个死循环,遍历MessageQueue中的消息
- queue.next(),当没有消息循环时,会在MessageQueue.next()中挂起。loop()中的循环不会结束。
- 只有当MessageQueue停止后,loop()中的死循环才会return
- 当获取到消息后,会调用msg.target,dispatchMessage(msg),处理消息。target即为Handler对象
Message next() {
......
for (;;) {
//--1
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;
//--2
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 (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
......
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
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(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
......
}
}
- 在next()中开启了一个死循环,调用了nativePollOnce(ptr, nextPollTimeoutMillis),当消息循环队列为空时,这个方法会通过底层epoll机制,使当前线程挂起,当有新消息时,会重新唤醒消息队列,不会使当前线程阻塞。
- 判断当msg != null && msg.target == null时,即当前消息为同步屏障时,阻塞当前MessageQueue中的同步消息的分发。同时异步消息可以正常执行。
- 当执行完MessageQueue中消息后,会执行IdleHandler中的queueIdle(),其返回值表示是否在下次MessageQueue空闲时再次执行。
4.消息处理
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
1.Handler分发处理消息的优先级为msg.callBack > mCallBack > HandleMessage()
5.其他
1.Handler.sendMessageAtFrontOfQueue()在消息队列头部添加一条Message
2.Handler.removeCallbacksAndMessages(null)删除MessageQueue中的所有Message
3.Looper.setMessageLogging(Printer)设置日志打印,在message分发时会输出相应log
转载自:https://juejin.cn/post/7096355472881483783