Android-Handler源码解析-MessageQueue
成员变量
// Log的Tag
private static final String TAG = "MessageQueue";
// 是否是Debug
private static final boolean DEBUG = false;
// 此消息队列是否可以退出,true为可以退出。
@UnsupportedAppUsage
private final boolean mQuitAllowed;
// natvie 层的消息队列的标识
@UnsupportedAppUsage
private long mPtr; // used by native code
// 此消息队列的头元素
@UnsupportedAppUsage
Message mMessages;
// 此消息队列的所有IdleHandler
@UnsupportedAppUsage
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
// 用于记录文件描述符
private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
//
private IdleHandler[] mPendingIdleHandlers;
// 此消息队列是否退出
private boolean mQuitting;
// 此消息队列是否是阻塞的
private boolean mBlocked;
// 下一个屏障token。
// 障碍由带有空target的消息表示,其arg1字段携带token。
@UnsupportedAppUsagejava
private int mNextBarrierToken;
复制代码
说明:
MessageQueue
为什么需要持有Message
,因为MessageQueue
是Message
集合。Message
相关介绍,请看三方库-Handler源码解析-Message。
创建MessageQueue
想要使用MessageQueue
,首先需要创建MessageQueue
,所以我们接下来看下它是如何被创建的。
new MessageQueue()
MessageQueue类
MessageQueue(boolean quitAllowed) {
// 记录是否允许退出
mQuitAllowed = quitAllowed;
// 初始化native层的消息队列,并记录其返回指针。
mPtr = nativeInit();
}
复制代码
MessageQueue
构造方法,为默认的,只能同包下调用,目前只有的Looper
创建时调用了,我们来看下Looper
的创建。
Looper构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); // 创建消息队列
mThread = Thread.currentThread();
}
复制代码
创建Looper
,可以通过Looper.prepare()
方法创建非主线程Looper
,它是允许退出的;可以通过Looper.prepareMainLooper()
方法创建主线程Looper
,它是不允许退出的。
说明:
Looper
创建相关介绍,请看三方库-Handler源码解析-Looper-创建Looper。
小结
MessageQueue
的创建,只能通过Looper
进行创建。主线程Looper
,它是不允许退出的;非主线程Looper
,它是允许退出的。
加入Message
当通过Handler
发送消息的时候,最终会调用MessageQueue
的enqueueMessage()
方法,我们来看一下。
Handler->enqueueMessage()
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// 调用MessageQueue的enqueueMessage()方法加入消息
return queue.enqueueMessage(msg, uptimeMillis);
}
复制代码
当Handler
发送消息的时候,最终都会走到Handler
的enqueueMessage()
方法,最终都是调用MessageQueue
的enqueueMessage()
方法进行加入。
说明:
Handler
发送消息相关介绍,请看三方库-Handler源码解析-Handler-发送Message。
接下来,我们来看下MessageQueue
的enqueueMessage()
方法。
enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
// 消息的目标Handler为空,抛出异常。
throw new IllegalArgumentException("Message must have a target.");
}
// 加锁,保证线程安全,因为加入Message操作(handler.send/post)可以在任何线程调用。
synchronized (this) {
if (msg.isInUse()) {
// 消息正在用(未被回收),再用则抛出异常。
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
// 退出中,再加入,则Log警告提示,并回收消息。
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; // 更新消息的when时间
Message p = mMessages; // 当前消息,默认为消息队列的Head元素。
boolean needWake; // 是否需要唤醒线程
if (p == null || when == 0 || when < p.when) {
// 新的头,将Message插入到队首,如果阻塞,则唤醒事件队列。
// 说明:
// p == null,说明头为空,队列为空。
// when == 0,说明需要排在队列前面(handler.sendMessageAtFrontOfQueue()方法调用传入)。
// when < p.when,说明此Message的执行时刻比Head的早,所以要将Message插入到队首。
msg.next = p; // 此Message链接Head(将此Message插入到队首)
mMessages = msg; // Head为此Message
needWake = mBlocked; // 如果阻塞,则唤醒。
} else {
// 队列有数据,并且非强制排在前面,并且此Message的执行时刻比Head的晚,将Message插入到队列中间。
// 通常我们不需要唤醒事件队列,除非在队列的头部有一个屏障,并且消息(msg)是队列中最早的异步消息。
// 阻塞,并且是头是屏障消息,并且是头是屏障消息,并且消息(msg)是异步消息,则先为唤醒。
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev; // 上一个元素
// 遍历队列,找到 Message 目标插入位置
for (;;) {
prev = p; // 上一个元素等于当前元素
p = p.next; // 当前元素等于下个元素,方便下次循环。
if (p == null || when < p.when) {
// 找到位置,退出循环。
// 说明:
// p == null,说明下个元素为空,到队尾了。
// when < p.when,说明此Message的执行时刻比下个元素的早;又因为走的是此else逻辑,所以此Message的执行时刻比上个元素的早,所以要将Message插入到此位置。
break;
}
if (needWake && p.isAsynchronous()) {
// 需要唤醒,并且下个消息是异步消息,即消息(msg)不是队列中最早的异步消息,则不需要唤醒。
needWake = false;
}
}
// 将Message插入队列的目标位置
msg.next = p;
prev.next = msg;
}
// 是否需要唤醒Native侧的MessageQueue
if (needWake) {
// 唤醒
nativeWake(mPtr);
}
}
return true;
}
复制代码
enqueueMessage()
方法,为向此消息队列中加入消息,
说明:
- 在
Looper
退出后,再向MessageQueue
加入消息将不再加入,并返回false
。- 加入消息,默认是按
Message
的what
升序进行加入,除非调用handler.sendMessageAtFrontOfQueue()
方法强制将消息加入到消息队列顶部。- 加入消息,需要判断是否需要唤醒,因为此线程之前可能进入阻塞,再加入消息,应该唤醒然后执行此消息。
小结
获取Message
next()
@UnsupportedAppUsage
Message next() {
// 如果消息loop已经退出并被销毁,则返回此处。
// 如果应用程序在退出后尝试重新启动looper,则可能会发生这种情况,这是不受支持的。
final long ptr = mPtr;
if (ptr == 0) {
// mPtr为0,说明loop已经退出了,直接返回null。
return null;
}
// 待处理的IdleHandler的数量,为-1代表是第一次初始化的状态。
int pendingIdleHandlerCount = -1;
// 下一次Poll超时时间,nativePollOnce()方法用。
int nextPollTimeoutMillis = 0;
// 开启循环
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// 阻塞方法,根据nextPollTimeoutMillis判断是否要阻塞。
// nextPollTimeoutMillis=-1,一直阻塞,不会超时。
// nextPollTimeoutMillis=0,不会阻塞,立即返回。
// nextPollTimeoutMillis>0,最长阻塞nextPollTimeoutMillis毫秒,如果期间有程序唤醒会立即返回。
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// 尝试检索下一条消息。如果发现则返回。
final long now = SystemClock.uptimeMillis(); // 当前时间
Message prevMsg = null; // 上一个消息
Message msg = mMessages; // 当前消息,默认为Head。
if (msg != null && msg.target == null) {
// 队首是屏障消息,的话被屏障阻挡。在队列中查找下一个异步Message。
// 说明:同步屏障只允许异步消息通过,所以得找到下一个异步Message。
// 使用do-while先获取到下一个数据,然后再判断,因为当前消息为屏障消息。
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 {
// 到达执行时刻,返回消息。
mBlocked = false; // 不阻塞状态
// Message出队
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) {
// 正在退出,返回null,以结束Looper.loop()。
dispose();
return null;
}
// 如果第一次空闲,则获取到要运行的IdleHandler的数量。
// Idle处理,仅在队列为空或队列中的第一个消息(可能是一个屏障),将在将来被处理的情况下运行。
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
// 第一次空闲,并且队列为空或者当前时间未到头的执行时刻,获取IdleHandler数量。
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// 没有空闲handlers要运行。循环并等待更多。
// 如果暂时没有 Idle Handler 需要处理,则进入下一次循环
// 为使下次循环如果出现新的 Idle Handler 能有机会执行
// 不重置计数器,仍为初始值 -1
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 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);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
复制代码
小结
移除Message
说明:
- 一个
MessageQueue
对应多个Message
,一个Message
对应一个Handler
,所以一个MessageQueue
可能对应多个Handler
(多个Handler
共用一个Looper
的情况)。- 一个
MessageQueue
可能对应多个相同Message
类型(Message
的target
、what
、obj
相同)或相同Callback
类型(Message
的target
、callback
、obj
相同)的消息。
removeMessages()
移除Messages
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
// Handler为空,直接返回,因为得需要Handler区分是哪个Handler的消息。
return;
}
// 加入同步锁,保证线程安全,因为Handler可能会在任意线程调用移除Message、Callback等方法。
synchronized (this) {
// 当前消息,默认为Head。
Message p = mMessages;
// 删除前面符合条件的所有Message(即队首是删除目标,从头开始删除,直到不符合为止)。
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
// 当前消息不为空,并且handler、what和目标相同,并且不匹配object或者匹配和目标相同,则移除当前消息。
Message n = p.next; // 下个消息
mMessages = n; // 因为要移除当前的,所以Head为下一个。
p.recycleUnchecked(); // 当前的消息回收
p = n; // 当前的为下一个,以便循环。
}
// 删除前面删除后剩余部分符合条件的所有Message。
while (p != null) {
Message n = p.next; // 下个消息
if (n != null) { // 有下个消息
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
// 下个消息handler、what和目标相同,并且不匹配object或者匹配和目标相同,则移除下个消息。
Message nn = n.next; // 下下个消息
n.recycleUnchecked(); // 下个消息回收
p.next = nn; // 下个消息为下下个消息,进行移除下个消息。
continue; // 当前的消息位置不变,以便再次进行判断是否下一个符合。
}
}
p = n; // 当前的为下个,以便循环寻找匹配上面if的。
}
}
}
复制代码
removeMessages(Handler, int, Object)
方法,为删除此MessageQueue
中所有与参数相同Message
类型(Message
的target
、what
、obj
相同)的消息。
说明:
- 它会先删除前面符合条件的所有
Message
(即队首是删除目标,从头开始删除,直到不符合为止),后删除前面删除后剩余部分符合条件的所有Message
。- 参数
object
为空,为不匹配Message
的obj
,否则匹配是否和object
相同。Handler
的removeMessages()
方法,调用的就是此方法。Handler
移除消息相关介绍,请看三方库-Handler源码解析-Handler-移除Messages、Callbacks。
移除Callbacks
void removeMessages(Handler h, Runnable r, Object object) {
if (h == null || r == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
复制代码
removeMessages(Handler, Runnable, Object)
方法,为删除此MessageQueue
中所有与参数相同Callback
类型(Message
的target
、callback
、obj
相同)的消息。
说明:
- 它的删除过程和
removeMessages(Handler, int, Object)
方法相同,只是把原来的Message
的what
判断改为了Message
的callback
判断。Handler
的removeCallbacks()
方法,调用的就是此方法。Handler
移除消息相关介绍,请看三方库-Handler源码解析-Handler-移除Messages、Callbacks。
removeCallbacksAndMessages()
void removeCallbacksAndMessages(Handler h, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
复制代码
removeCallbacksAndMessages(Handler, Object)
方法,为删除此MessageQueue
中此Handler
发出的所有Message
、Callback
(Message
的target
、obj
相同)。
说明:
- 它的删除过程和
removeMessages(Handler, int, Object)
、removeMessages(Handler, Runnable, Object)
方法相同,只是把原来的Message
的what
判断或callback
判断去掉了。Handler
的removeCallbacksAndMessages()
方法,调用的就是此方法。- 可以调用
handler.removeCallbacksAndMessages(null)
删除此Handler
的所有Messages
、Callbacks
。Handler
移除消息相关介绍,请看三方库-Handler源码解析-Handler-移除Messages、Callbacks。
小结
是否有Message
hasMessages()
是否有Message
boolean hasMessages(Handler h, int what, Object object) {
if (h == null) {
// Handler为空,直接返回。
return false;
}
// 加入同步锁,保证线程安全,因为Handler可能会在任意线程调用是否有Message、Callback等方法。
synchronized (this) {
// 当前消息,默认为Head。
Message p = mMessages;
// 遍历判断是否有
while (p != null) {
if (p.target == h && p.what == what && (object == null || p.obj == object)) {
// 当前消息handler、what和目标相同,并且不匹配object或者匹配和目标相同,则返回true。
return true;
}
p = p.next; // 当前的为下一个,以便循环。
}
return false; // 没找到,返回false。
}
}
复制代码
hasMessages(Handler, int, Object)
方法,为判断此MessageQueue
中是否有与参数相同Message
类型(Message
的target
、what
、obj
相同)的消息。
说明:
- 它会遍历
MessageQueue
中的所有Message
,只要有一条符合条件,就返回ture
;否则返回false
。- 参数
object
为空,为不匹配Message
的obj
,否则匹配是否和object
相同。Handler
的hasMessages()
方法,调用的就是此方法。Handler
是否有消息相关介绍,请看三方库-Handler源码解析-Handler-是否有Messages、Callbacks。
是否有Callback
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
boolean hasMessages(Handler h, Runnable r, Object object) {
if (h == null) {
return false;
}
synchronized (this) {
Message p = mMessages;
while (p != null) {
if (p.target == h && p.callback == r && (object == null || p.obj == object)) {
return true;
}
p = p.next;
}
return false;
}
}
复制代码
hasMessages(Handler, Runnable, Object)
方法,为判断此MessageQueue
中是否有与参数相同Callback
类型(Message
的target
、callback
、obj
相同)的消息。
说明:
- 它的判断过程和
hasMessages(Handler, int, Object)
方法相同,只是把原来的Message
的what
判断改为了Message
的callback
判断。Handler
的hasCallbacks()
方法,调用的就是此方法。Handler
是否有消息相关介绍,请看三方库-Handler源码解析-Handler-是否有Messages、Callbacks。
是否有Messages或Callbacks
boolean hasMessages(Handler h) {
if (h == null) {
return false;
}
synchronized (this) {
Message p = mMessages;
while (p != null) {
if (p.target == h) {
return true;
}
p = p.next;
}
return false;
}
}
复制代码
hasMessages(Handler)
方法,为判断此MessageQueue
中是否有此Handler
发出的所有Message
、Callback
(Message
的target
相同)。
说明:
- 它的判断过程和
hasMessages(Handler, int, Object)
、hasMessages(Handler, Runnable, Object)
方法相同,只是把原来的Message
的what
、obj
判断或callback
、obj
判断去掉了。Handler
的hasMessagesOrCallbacks()
方法,调用的就是此方法。Handler
是否有消息相关介绍,请看三方库-Handler源码解析-Handler-是否有Messages、Callbacks。
小结
退出MessageQueue
quit()
void quit(boolean safe) {
if (!mQuitAllowed) {
// 不允许退出(只有MainLooper不允许退出),再退出,抛出异常(主线程不运行退出)。
throw new IllegalStateException("Main thread not allowed to quit.");
}
// 加入同步锁,保证线程安全,因为Looper可能会在任意线程调用退出方法。
synchronized (this) {
if (mQuitting) {
// 已经退出中,再退出,不操作。
return;
}
// 标记退出中
mQuitting = true;
// 判断是否是安全的退出
if (safe) {
// 安全的,移除未来(当前时间点以后)的所有消息。
removeAllFutureMessagesLocked();
} else {
// 不安全的,移除所有消息。
removeAllMessagesLocked();
}
// 唤醒,防止在阻塞中。
nativeWake(mPtr);
}
}
复制代码
quit()
方法,为退出此MessageQueue
,会标记mQuitting
为true
,参数safe
为是否安全退出,安全退出会调用removeAllFutureMessagesLocked()
方法,移除未来(当前时间点以后)的所有消息。不安全退出会调用removeAllMessagesLocked()
方法,移除所有消息。
说明:
- 不允许退出的
MessageQueue
,退出后会抛出异常。Looper
的quit()
、quitSafely()
方法,调用的就是此方法。Looper
退出相关介绍,请看三方库-Handler源码解析-Looper-退出Looper。
我们先来看一下,不安全退出调用的removeAllMessagesLocked()
方法。
removeAllMessagesLocked()
private void removeAllMessagesLocked() {
// 当前消息,默认为Head。
Message p = mMessages;
// 遍历所有消息,然后进行回收。
while (p != null) {
Message n = p.next; // 下个消息
p.recycleUnchecked(); // 回收当前消息
p = n; // 当前为下个,以便循环。
}
// Head为空,断开和其它消息的链接,使队列为空。
mMessages = null;
}
复制代码
removeAllMessagesLocked()
方法,为移除此MessageQueue
中所有消息。
我们再来看一下,安全退出调用的removeAllFutureMessagesLocked()
方法。
removeAllFutureMessagesLocked()
private void removeAllFutureMessagesLocked() {
// 当前时间
final long now = SystemClock.uptimeMillis();
Message p = mMessages; // 当前消息,默认为Head。
if (p != null) {
// 队列有数据,进行移除。
if (p.when > now) {
// 队首的执行时刻大于现在的时间,说明之后的消息都是未来(以后)执行的,所以移除所有消息。
removeAllMessagesLocked();
} else {
// 非全部未来(以后)执行,找到位置,进行移除之后的。
Message n; // 下个消息
// 遍历,找到移除始发位置。
for (;;) {
n = p.next; // 下个消息
if (n == null) {
// 没有下个消息,说明到队尾了,还未走下面if退出,说明所有消息都是以前的消息,直接返回。
return;
}
if (n.when > now) {
// 下个消息执行时刻大于当前时间,再加上队列里的时刻是从小到大有序的,
// 则说明当前时间,比当前消息执行时刻大,比下个消息执行时刻小,所以即找到位置,退出遍历。
break;
}
p = n; // 当前为下个,以便循环。
}
// 移除之后的
p.next = null; // 断开后续链接,即已经移除成功。
// 遍历之后所有消息,然后进行回收。
do {
p = n;
n = p.next;
p.recycleUnchecked(); // 回收消息
} while (n != null);
}
}
}
复制代码
removeAllFutureMessagesLocked()
方法,为移除此MessageQueue
中未来(当前时间点以后)的所有消息。
小结
同步屏障
postSyncBarrier() @hide removeSyncBarrier() @hide
postSyncBarrier
postSyncBarrier()
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
复制代码
private int postSyncBarrier(long when) {
// 加入一个新的同步屏障token。
// 我们不需要唤醒队列,因为屏障的目的是让它停滞。
synchronized (this) {
// 同步屏障消息可以有多个,用token区分,token通过mNextBarrierToken累加维护。
final int token = mNextBarrierToken++;
// 获取一个屏障消息(target为null)
final Message msg = Message.obtain();
msg.markInUse(); // 标记消息在用
msg.when = when; // 记录执行时刻
msg.arg1 = token; // 记录token
// 根据when排序找到插入位置。
Message prev = null; // 上个消息
Message p = mMessages; // 当前消息,默认为Head。
if (when != 0) {
while (p != null && p.when <= when) {
// 当前不为空,并且当前时间小于目标时间,继续查找。
prev = p; // 上个为当前
p = p.next; // 当前为下个,以便循环。
}
}
// 进行插入
if (prev != null) {
// 进入了while循环,找到了位置,将消息在此位置插入。
msg.next = p;
prev.next = msg;
} else {
// 未进入while循环,未找到了位置,将消息在队首插入。
// 未进入while循环,说明:队列为空,或队里的所有Message时刻都比屏障Message要晚。
msg.next = p;
mMessages = msg;
}
// 返回toke,为了移除用。
return token;
}
}
复制代码
removeSyncBarrier
removeSyncBarrier()
public void removeSyncBarrier(int token) {
// 从队列中删除同步屏障token。
// 如果队列不再被屏障阻碍,那么唤醒它。
synchronized (this) {
Message prev = null; // 上个消息
Message p = mMessages; // 当前消息,默认为Head。
// 遍历队列找到此token的屏障Message
while (p != null && (p.target != null || p.arg1 != token)) {
// 当前不为空,并且当前的不是屏障消息或者是屏障消息但是token不相等,继续查找。
prev = p;
p = p.next;
}
if (p == null) {
// 队列为空,或到末尾了没找到,抛出异常(指定的消息队列同步屏障token尚未发布或已被删除)。
throw new IllegalStateException("The specified message queue synchronization "
+ " barrier token has not been posted or has already been removed.");
}
final boolean needWake; // 是否需要唤醒
// 进行移除
if (prev != null) {
// 进入了while循环,找到了位置,将消息在此位置移除。
prev.next = p.next;
needWake = false; // 不需要唤醒
} else {
// 未进入while循环,未找到了位置,将消息在队首移除。
// 未进入while循环,说明:队列为空,或队首就是此屏障消息。
mMessages = p.next;
// 如果队列为空,或队首是屏障消息,则唤醒。
needWake = mMessages == null || mMessages.target != null;
}
// 回收消息
p.recycleUnchecked();
// 判断是否应该唤醒,如果loop退出,那么它已经醒了。
if (needWake && !mQuitting) {
// 唤醒
nativeWake(mPtr);
}
}
}
复制代码
IdleHandler
IdleHandler类
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/
// 当消息队列耗尽消息并将等待更多消息时调用。返回true以保持空闲处理程序处于活动状态,返回false以移除它。如果队列中仍有消息挂起,但它们都被调度到当前时间之后,则可以调用此函数。
boolean queueIdle();
}
复制代码
addIdleHandler()
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
复制代码
removeIdleHandler()
public void removeIdleHandler(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
}
}
复制代码