原文地址:https://juejin.cn/post/7041576680648867877
知识点:IdleHandler 的执行时机是主线程无消息或者未到执行时机。并且IdleHandler的执行方式是一次性执行所有的IdleHandler任务,如果IdleHandler执行耗时,也会影响主队列中的任务执行。
//MessageQueue.java
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
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);
...
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
//1
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)];
}
//2
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
//3
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);
}
//4
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;
}
}
//5
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
正确使用方式:
private static List<Runnable> uiTasks = new ArrayList<>();
public static UIPoolManager addTask(Runnable runnable) {
tasks.add(runnable);
return this;
}
public static UIManager runUiTasks() {
NullHelper.requireNonNull(uiTasks);
IUiTask iUiTask = new IUiTask() {
@Override
public boolean queueIdle() {
if (!uiTasks.isEmpty()) {
Runnable task = uiTasks.get(0);
task.run();
uiTasks.remove(task);
}
//逐次取一个任务执行 避免占用主线程过久
return !uiTasks.isEmpty();
}
};
Looper.myQueue().addIdleHandler(iUiTask);
return this;
}
uiTasks 是所有的IdleHandler 需要执行的任务,每次只执行一个任务,当uiTasks有任务,返回true,等待下一次空闲时机执行,否则返回false。