文章目录
源码分析Handler消息模型
Handler
职责
从开发者角度来看,可分为
- Message的发送者
- Message的处理者
- Message的移除者
首先我们老看Handler的成员变量
public class Handler {
@UnsupportedAppUsage
final Looper mLooper;//当前线程对应的Looper对象
final MessageQueue mQueue;//Looper里维护的对应MessageQueue
@UnsupportedAppUsage
final Callback mCallback;//当message没有callback的时候,会判断走当前的Callback回调
final boolean mAsynchronous;//是否是异步执行
@UnsupportedAppUsage
IMessenger mMessenger;//用于跨进程发送消息
}
//Handler.java
public class Handler {
public Handler(@Nullable Callback callback, boolean async) {
//为false,用于检测是否是弱引用或者静态变量,检测内存泄露
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());
}
}
//创建当前线程Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//从Looper中取出MessageQueue
mQueue = mLooper.mQueue;
//回调赋值
mCallback = callback;
//是否异步
mAsynchronous = async;
}
}
//Looper.java
public static @Nullable Looper myLooper() {
return sThreadLocal.get();//从当前线程中获取对应Looper,具体Looper后面详细讲解
}
1.Message的发送者
public class Handler{
//发送消息
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);//执行延时为0的发送
}
//发送延迟处理消息
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {//容错判断
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//发送相对于当前时间的任务消息
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
//难道构造函数中获取的MessageQueue
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);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;//将当前Handler对象赋值给Message的target
msg.workSourceUid = ThreadLocalWorkSource.getUid();//返回该线程当前执行的代码的UID。
//设置异步执行
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//交由MessageQueue处理具体的队列逻辑
return queue.enqueueMessage(msg, uptimeMillis);
}
}
//MessageQueue.java
public final class MessageQueue{
boolean enqueueMessage(Message msg, long when) {
//hanler为null,抛出异常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//相同message已经被处理,抛出异常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//调用了quit方法取消终止循环,就return掉
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
//更改Message使用标记
msg.markInUse();
//更新执行时间值
msg.when = when;
//当前MessageQueue的Message链表
Message p = mMessages;
//需要唤醒
boolean needWake;
//如果当前Messages没有 || 立即执行 || 当前时间比Message链表头结点时间更短,则将当前节点作为第一个结点加入
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;
//根据when寻找插入位置并插入
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;
}
// 我们可以假设mPtr!= 0,因为mQuitting为false。
if (needWake) {
//native方法唤醒时间队列
nativeWake(mPtr);
}
}
return true;
}
}
上面小节介绍的是Handler作为发送者的具体做的事情,Handler通过sendMessage等其他方法将消息Message加入MessageQueue里面的消息链表里
2.Message的处理者
再Looper.loop()中循环取消息调用msg.target.dispatchMessage(msg);来处理时间,其中的target有讲过,是对应当前的Handler对象,所以我们来看dispatchMessage(msg)方法
public class Handler{
//处理消息
public void dispatchMessage(@NonNull Message msg) {
//如果message中设置了callback,则回调callback。
//callback是通过post方法发送消息赋值的
if (msg.callback != null) {
handleCallback(msg);
} else {
//如果成员变量mCallback已设置,则回调mCallback.handleMessage处理
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//如果上面都没有,使用handleMessage处理消息,该方法是一个空实现,需要使用者重写
handleMessage(msg);
}
}
//子类必须实现
public void handleMessage(@NonNull Message msg) {
}
}
所以Handler也是消息的处理者,是消息的入口与出口,这样的设计让我们在使用时无需关心Looper和MessageQueue详细细节是怎么处理的,同时可以有多个handler来向消息队列里加入消息并处理,方便在各个地方使用。
3.Message的移除者
三个方法都是调用MessageQueue对应的remove方法
public class Handler{
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeMessages(int what, @Nullable Object object) {
mQueue.removeMessages(this, what, object);
}
public final void removeCallbacksAndMessages(@Nullable Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
}
都是调用MessageQueue来移除队列
Looper
职责
负责无限循环从MessageQueue中取出消息
Looper的创建
Looper是私有构造函数,所以需要使用Looper.prepare来创建Looper对象
public final class Looper {
//Looper是一个私有的构造函数,在里面创建了MessageQueue队列和获取当前线程
private Looper(boolean quitAllowed) {
//获取当前线程,参数quitAllowed,主线程不能退出传的false,子线程传的true
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//无参方法,创建一个允许退出的Looper
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//sThreadLocal是一个存储Looper的线程对象,重复创建Looper对象,则抛错
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建Looper对象并设置给sThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
}
//创建主线程Looper
public static void prepareMainLooper() {
//主线程不允许退出,所以传false
prepare(false);
synchronized (Looper.class) {
//成员变量保存主线程Looper,重复创建抛出异常
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//从sThreadLocal获取Looper,赋值成员变量
sMainLooper = myLooper();
}
}
//获取当前线程Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
Looper循环
Looper顾名思义,是用来循环的,其中具体操作在loop()方法中
public final class Looper {
/**
* 在此线程中运行消息队列。 确保调用{@link #quit()}以结束循环
**/
public static void loop() {
//获取当前线程Looper
final Looper me = myLooper();
//未调用prepare创建,抛出异常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取到Looper中创建的消息队列
final MessageQueue queue = me.mQueue;
//确保此线程的身份是本地进程的身份,并跟踪该身份令牌实际上是什么.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 允许使用系统属性覆盖阈值。例如
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
//标志是否缓慢
boolean slowDeliveryDetected = false;
//开始无限循环取出消息
for (;;) {
// 可能阻塞,具体去取出消息,在后续MessageQueue中讲解
Message msg = queue.next();
if (msg == null) {
// 没有消息表示消息队列正在退出。
return;
}
// 如果UI事件设置了记录器,则必须在局部变量中
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// 确保观察者在处理交易时不会改变,可以通过set方法监听
final Observer observer = sObserver;
//获取到缓慢或发送日志的阈值
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresholdOverride;
}
//都大于0,则缓慢发送
final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
//分发阈值大于0,则日志缓慢分发
final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
//如果是缓慢发送,则需要记录开始时间
final boolean needStartTime = logSlowDelivery || logSlowDispatch;
//如果缓慢分发,则需要记录结束时间
final boolean needEndTime = logSlowDispatch;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
//分发开始时间
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
Object token = null;
//告诉观察者开始分发立即调用
if (observer != null) {
token = observer.messageDispatchStarting();
}
//设置消息资源Uid
long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
try {
//实际交由消息对应Hander的dispatchMessage处理
msg.target.dispatchMessage(msg);
//告诉观察者,消息已经分发
if (observer != null) {
observer.messageDispatched(token, msg);
}
//记录消息结束时间
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
//告诉观察者分发出现异常
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
//重置状态
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//下面一系列记录日志
if (logSlowDelivery) {
if (slowDeliveryDetected) {
if ((dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
slowDeliveryDetected = false;
}
} else {
if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
msg)) {
// Once we write a slow delivery log, suppress until the queue drains.
slowDeliveryDetected = true;
}
}
}
if (logSlowDispatch) {
showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
//确保在分派线程的过程中没有破坏线程的身份.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//回收message,主要是重置成员变量值并加入消息池,方便后续继续复用该Message
msg.recycleUnchecked();
}
}
}
MessageQueue
职责
使用链表存储消息
构造函数和部分成员变量
//MessageQueue.java
public final class MessageQueue {
//是否允许退出
private final boolean mQuitAllowed;
//当前消息,数据结构是链表
Message mMessages;
//是否正在推出
private boolean mQuitting;
// 指示next()是否被阻止在pollOnce()中以非零超时等待
private boolean mBlocked;
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//过native方法初始化消息队列,其中mPtr是供native代码使用
mPtr = nativeInit();
}
}
//native代码
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
//创建出MessageQueue对象
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
//未能创建成功抛出异常
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return;
}
//添加强引用指针
nativeMessageQueue->incStrong(env);
//设置messageQueue
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
NativeMessageQueue* nativeMessageQueue) {
//将队列地址设置保存在mPtr中
env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
reinterpret_cast<jint>(nativeMessageQueue));
}
//创建nativeMessageQueue
NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
//获取到线程对应Looper
mLooper = Looper::getForThread();
//如果未创建,则创建Looper并设置进线程中
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
消息入队列
Handler获取的MessageQueue调用了enqueueMessage方法将消息入队列,已经在上面的Handler中讲解了,这里再列举一遍
public final class MessageQueue {
boolean enqueueMessage(Message msg, long when) {
//hanler为null,抛出异常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//相同message已经被处理,抛出异常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//调用了quit方法取消终止循环,就return掉
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
//标记消息已使用
msg.markInUse();
//更新执行时间值
msg.when = when;
//当前MessageQueue的Message链表
Message p = mMessages;
//需要唤醒
boolean needWake;
//如果当前Messages没有 || 立即执行 || 当前时间比Message链表头结点时间更短,则将当前节点作为第一个结点加入
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;
//根据when寻找插入位置并插入
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;
}
// 我们可以假设mPtr!= 0,因为mQuitting为false。
if (needWake) {
//native方法唤醒时间队列
nativeWake(mPtr);
}
}
return true;
}
}
消息出队列
Looper调用MessageQueue的next()方法去除消息
public final class MessageQueue {
Message next() {
// 如果消息循环已经退出并被处理,请返回此处。
// 如果应用程序尝试退出后不支持的循环程序,则会发生这种情况
final long ptr = mPtr;
//当消息循环已经退出,则直接返回
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; //只有第一次赋值为-1
//初始化下一次poll唤醒延时
int nextPollTimeoutMillis = 0;
for (;;) {
//只要延时不为0,刷新待定命令
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞操作,当等待nextPollTimeoutMillis时长,或者消息队列被唤醒,都会返回,
//***这就是主线程为什么一直不阻塞主线程
//实际调用的是c++层ALooer::pollOnce方法,通过 mCondition.wait来等待
//mCondition.waitRelative(mLock, waitUntilNs - nowNs);
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// 尝试检索下一条消息。 如果找到则返回。
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// 查询MessageQueue中的下一条异步消息
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 设置下一次轮询消息的超时时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 获取一条消息,并返回 zz
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 {
//没有消息
nextPollTimeoutMillis = -1;
}
// 现在已处理所有挂起的消息,请处理退出消息。
if (mQuitting) {
dispose();
return null;
}
// 如果是第一次空闲,则获取要运行的惰轮数量。
//空闲句柄仅在队列为空或将来要处理队列中的第一条消息(可能是屏障)时才运行。
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// 没有空闲的处理程序可以运行。 循环并等待更多。
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 只有第一次循环时,会运行idle handlers,执行完成后,重置pendingIdleHandlerCount为0.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // 释放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);
}
}
}
// 将空闲处理程序计数重置为0,这样我们就不再运行它们。
pendingIdleHandlerCount = 0;
//调用空闲处理程序时,可能已经传递了一条新消息,因此请返回并再次查找未决消息,而无需等待。
nextPollTimeoutMillis = 0;
}
}
}
消息移除
通过Handler的MessageQueue.removeMessages移除消息
public final class MessageQueue {
void removeMessages(Handler h, int what, Object object) {
//handler不能为空
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// 当是当前消息时,移除头结点
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// 移除头结点之后的所有消息
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
}
退出消息循环
public final class MessageQueue {
void quit(boolean safe) {
//主线程不能退出,否则抛出错误
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
//已经调用退出拦截
if (mQuitting) {
return;
}
//改变退出标识
mQuitting = true;
//是否安全退出
if (safe) {
//只移除大于当前时间的结点
removeAllFutureMessagesLocked();
} else {
//直接遍历所有Message
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
//直接遍历移除所有message结点
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
//移除大于当前时间结点
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages;
if (p != null) {
if (p.when > now) {
removeAllMessagesLocked();
} else {
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
if (n.when > now) {
break;
}
p = n;
}
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null);
}
}
}
}
Message
Message设计
复用
public final class Message implements Parcelable {
/** 构造函数 (但是最好调用{@link #obtain() Message.obtain()}).
*/
public Message() {
}
public static Message obtain() {
//首先Message池里面取出消息,如果sPool没有消息,接直接new
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
}
Message设计了一个最大容量为50的Message复用池,各个线程均从当前Message池中取出消息重复使用,防止过多的new操作,耗费性能
总结
Android的所有线程的消息处理,都是通过Handler来发送和处理,然后通过Looper循环从MessageQueue中取出消息,交由Handler处理