handler-主线程消息循环的创建流程
2019-08-23 本文已影响0人
lvcs
1.在ActivityThread的main方法中开启主线程的消息循环
在其它线程中创建Looper可使用 Looper.prepare()方法
//ActivityThread#main
public static void main(String[] args) {
......
//将当前线程初始化为looper,将其标记为应用程序的主循环。
Looper.prepareMainLooper();
.......
//让Looper工作处理消息,开始消息循环
Looper.loop();
.......
}
2.创建UI线程Looper
在创建Looper的同时,创建MessageQueue,绑定当前线程,并将Looper放入ThreadLocal进行线程分离,每个线程将调用自己的Looper进行使用。
//Looper
public final class Looper {
//装载不同线程Looper的容器
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//应用程序的主循环器,它位于应用程序的主线程中
private static Looper sMainLooper;
//与此Looper关联的消息队列
final MessageQueue mQueue;
//与此Looper关联的线程
final Thread mThread;
//Looper构造方法 创建消息队列,获取当前线程
private Looper(boolean quitAllowed) {
//创建消息队列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
//创建主程序Looper
public static void prepareMainLooper() {
//创建Looper 主线程传入false参数,禁止退出消息循环(其它线程都为true,可退出)
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//返回与当前线程关联的Looper对象。如果调用线程未与Looper关联,则返回null。
sMainLooper = myLooper();
}
}
//创建新Looper,并将其放入ThreadLocal中
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));
}
3.创建MessageQueue
分别创建Java层MessageQueue和native层的MessageQueue
//MessageQueue
public final class MessageQueue {
//是否可以退出消息队列
private final boolean mQuitAllowed;
//当前looper待处理的消息
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
private IdleHandler[] mPendingIdleHandlers;
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//创建native层的MessageQueue
mPtr = nativeInit();
}
}
//android_os_MessageQueue.cpp#android_os_MessageQueue_nativeInit
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast<jlong>(nativeMessageQueue);
}
//android_os_MessageQueue.cpp#NativeMessageQueue
//Native Looper调用静态方法getForThread(),获取当前线程中的Looper对象。如果为空,则创建Native Looper对象
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
4.Looper.loop()开启循环
//Looper
public static void loop() {
//在ThreadLocal中获取当前线程的Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取与此Looper绑定的MessageQueue
final MessageQueue queue = me.mQueue;
......
//死循环
for (;;) {
// //获取MessageQuene消息队列的消息.
Message msg = queue.next();
if (msg == null) {
//如果没有消息则return,阻塞在这里等待获取Message。
return;
}
......
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
//msg.target 是Message里的Handler 写入跟踪消息已经开始
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
......
try {
//让与Message关联的Handler通过dispatchMessage()处理Message。
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
//结束
Trace.traceEnd(traceTag);
}
}
......
//重新循环可能正在使用的消息
msg.recycleUnchecked();
}
}
5.MessageQueue .next()取出消息
消息的处理会优先处理Native层的消息,其次才处理Java层的消息。
在正常时候,我们发送的Message全都是同步消息,当然我们也可以发送异步消息。
当开启了同步障碍,Looper在获取下一个要执行的消息时,会在链表中寻找第一个要执行的异步消息,如果没有找到异步消息,就让当前线程沉睡。实质上是一个对消息队列的优先级实现。
//MessageQueue
Message next() {
final long ptr = mPtr;
//如果native层的looper被放弃的时候(调用了quit方法)返回null
if (ptr == 0) {
return null;
}
//-1仅在第一次迭代期间
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
//死循环
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞方法,主要是通过native层的epoll监听文件描述符的写入事件来实现的。
//如果nextPollTimeoutMillis=-1,一直阻塞不会超时
//如果nextPollTimeoutMillis=0,不会阻塞,立即返回。
//如果nextPollTimeoutMillis>0,最长阻塞nextPollTimeoutMillis毫秒(超时),如果期间有程序唤醒会立即返回。
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
//获取系统开机到现在的时间
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
//msg是最后查找到的消息,这里初始化为消息队列的队头消息
Message msg = mMessages;
//如果当前开启了同步障碍
if (msg != null && msg.target == null) {
//msg.target == null表示此消息为消息屏障(通过postSyncBarrier方法发送来的)
//处理同步障碍,会循环找出第一个异步消息(同步障碍消息)
//所有同步消息都将忽略(平常发送的一般都是同步消息)
do {
prevMsg = msg;
msg = msg.next;
// 如果这个消息是同步的,那么继续向下找异步的
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 如果当前消息的执行时间没到,让它沉睡到下个消息的执行时间,设置一下阻塞时间nextPollTimeoutMillis
//进入下次循环的时候会调用nativePollOnce(ptr, nextPollTimeoutMillis)进行阻塞;
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//正常取出消息,不需要等待时间或者等待时间已经到了,那么直接返回该消息
//从消息队列中删除待返回的msg(剪断链表)
//设置mBlocked = false代表目前没有阻塞
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;
}
//获取空闲时处理任务的handler 用于发现线程何时阻塞等待更多消息的回调接口。
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
//如果空闲时处理任务的handler个数为0,继续让线程阻塞
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
//判断当前空闲时处理任务的handler是否是为空
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(TAG, "IdleHandler threw exception", t);
}
//如果不保存空闲任务,执行完成后直接删除
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
//重置空闲的handler个数,因为不需要重复执行
pendingIdleHandlerCount = 0;
//当执行完空闲的handler的时候,新的native消息可能会进入,所以唤醒Native消息机制层
nextPollTimeoutMillis = 0;
}
}