MessagemMessages;booleanenqueueMessage(Messagemsg,longwhen){synchronized(this){if(msg.isInUse()){//发送的消息必须是闲置状态的
thrownewIllegalStateException(msg+" This message is already in use.");}if(mQuitting){//mQuitting是一个状态,只有MessageQueue的quit方法调用时才这个状态才会为true
msg.recycle();//回收
returnfalse;}msg.markInUse();//改状态为使用中
msg.when=when;//注意这里赋值
Messagep=mMessages;booleanneedWake;//重点是时间的比较,如果新的msg的时间早于当前的message,那么就把新的msg放在头部。
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();//如果是异步消息
Messageprev;for(;;){//又一个死循环,用来向下遍历队列,
prev=p;//把当前的msg设为前一个msg
p=p.next;//当前的msg指向下一个msg
if(p==null||when<p.when){//如果我们设置时间的早于msg的时间,那么就停止遍历
break;}if(needWake&&p.isAsynchronous()){needWake=false;}}msg.next=p;// invariant: p == prev.next
prev.next=msg;}if(needWake){nativeWake(mPtr);//唤醒线程处理消息
}}returntrue;}
@UnsupportedAppUsageMessagenext(){//当loop执行了quit后,程序可能会重启looper,就会返回到这里。
finallongptr=mPtr;if(ptr==0){returnnull;}intpendingIdleHandlerCount=-1;//只有在第一次遍历时是-1
intnextPollTimeoutMillis=0;for(;;){if(nextPollTimeoutMillis!=0){//用来在线程要进入阻塞之前跟内核线程发送消息,防止用户线程长时间的持有某个对象
Binder.flushPendingCommands();}nativePollOnce(ptr,nextPollTimeoutMillis);//告诉linux的epoll:你丫可以睡nextPollTimeoutMillis这么长时间了!直到handler发送消息调用`mQueue.enqueueMessage()`方法时会被唤醒,或者当前消息到时间时也会被唤醒。
synchronized(this){// 尝试检索下一个msg,找到就返回
finallongnow=SystemClock.uptimeMillis();MessageprevMsg=null;Messagemsg=mMessages;if(msg!=null&&msg.target==null){//靠栅栏停滞,找到下一个非异步msg
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;if(prevMsg!=null){prevMsg.next=msg.next;}else{//如果不是异步消息,prevMsg就是null
mMessages=msg.next;//往上提一位
}msg.next=null;//打断链条单独取出
if(DEBUG)Log.v(TAG,"Returning message: "+msg);msg.markInUse();//改变状态为使用中
returnmsg;//返回
}}else{//如果当前没有消息,把唤醒时钟设为-1,那么意味着线程会沉睡Integer.MaxValue
nextPollTimeoutMillis=-1;}// Process the quit message now that all pending messages have been handled.
if(mQuitting){dispose();returnnull;}///接下来就是喜闻乐见的idleHandler了
if(pendingIdleHandlerCount<0&&(mMessages==null||now<mMessages.when)){pendingIdleHandlerCount=mIdleHandlers.size();//如果没有添加过idleHandler,那么就是0
}if(pendingIdleHandlerCount<=0){//如果没有idleHandler需要执行,那就继续loop
mBlocked=true;continue;}//初始化一个固定长度的数组
if(mPendingIdleHandlers==null){mPendingIdleHandlers=newIdleHandler[Math.max(pendingIdleHandlerCount,4)];}mPendingIdleHandlers=mIdleHandlers.toArray(mPendingIdleHandlers);}// 遍历执行所有的idleHandler.
//只有在第一次循环时才会执行到这个代码块
for(inti=0;i<pendingIdleHandlerCount;i++){finalIdleHandleridler=mPendingIdleHandlers[i];mPendingIdleHandlers[i]=null;// 强行释放数组中的idleHandler,不会影响ArrayList中的idleHandler和当前正在使用的idleHandler。
booleankeep=false;try{keep=idler.queueIdle();//回调queueIdle方法
}catch(Throwablet){Log.wtf(TAG,"IdleHandler threw exception",t);}if(!keep){synchronized(this){mIdleHandlers.remove(idler);}}}//重置计数
pendingIdleHandlerCount=0;nextPollTimeoutMillis=0;}}
IdleHandler
1
2
3
4
5
6
7
8
9
10
11
12
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
* 当线程将要锁定(等待更多消息)时就会回调queueIdle方法
*/publicstaticinterfaceIdleHandler{/**
* 当MessqgeQueue已经处理完所有的message,并且将要进入睡眠和等待时这个方法才会被调用。
* 返回true可以使IdleHandler保持激活状态,那么当下次线程空闲了还会调用,返回false就会移除IdleHandler。
*/booleanqueueIdle();}
publicvoidaddIdleHandler(@NonNullIdleHandlerhandler){if(handler==null){thrownewNullPointerException("Can't add a null IdleHandler");}synchronized(this){mIdleHandlers.add(handler);}}
//条件1:没有msg或msg还没到执行的时候
if(msg!=null){if(now<msg.when){//msg时间晚于当前时间
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();returnmsg;}}else{// No more messages.
nextPollTimeoutMillis=-1;}//条件2:looper没有停止
if(mQuitting){dispose();returnnull;}//条件3:不存在IdleHandler的话就重新遍历
if(pendingIdleHandlerCount<=0){// No idle handlers to run. Loop and wait some more.
mBlocked=true;continue;}