//在native层,消息循环的休眠和唤醒使用了Linux内核的epoll机制和pipe
Looper.prepareMainLooper();//ActivityThreadpublicstaticvoidprepareMainLooper(){//不能退出消息队列,传递falseprepare(false);synchronized(Looper.class){if(sMainLooper != null){thrownewIllegalStateException("The main Looper has already been prepared.");}sMainLooper =myLooper();}}//ActivityThreadprivatestaticvoidprepare(boolean quitAllowed){//不为空表示当前线程已经创建了Looperif(sThreadLocal.get()!= null){//每个线程只能创建一个Looper thrownewRuntimeException("Only one Looper may be created per thread");}//创建Looper并设置给sThreadLocalsThreadLocal.set(newLooper(quitAllowed));}//ActivityThreadprivateLooper(boolean quitAllowed){//创建MessageQueuemQueue =newMessageQueue(quitAllowed);//绑定当前线程mThread = Thread.currentThread();}//Looperpublicstatic@Nullable Looper myLooper(){//获取Looperreturn sThreadLocal.get();}/*
1.获取当前线程对应的Looper
2.获取对应的MessageQueue
3.拿到msg消息
4.msg消费
*///Looperpublicstaticvoidloop(){//里面调用了sThreadLocal.get()获得刚才创建的Looper对象final Looper me =myLooper();if(me == null){//如果Looper为空则会抛出异常thrownewRuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}final MessageQueue queue = me.mQueue;for(;;){//这是一个死循环,从消息队列不断的取消息Message msg = queue.next();// might blockif(msg == null){//由于刚创建MessageQueue就开始轮询,队列里是没有消息的,等到Handler sendMessage enqueueMessage后队列里才有消息// No message indicates that the message queue is quitting.return;}//msg.target就是绑定的Handler,详见后面Message的部分,Handler开始msg.target.dispatchMessage(msg);msg.recycleUnchecked();}}/*
在dispatchMessage方法中,message中callback是一个Runnable对象,如果callback不为空,则直接调用callback的run方法。
否则判断mCallback是否为空,mCallback在Handler构造方法中初始化,在主线程通过无参的构造方法,new出来的为null,所以会直接执行后面的handleMessage()方法。
*///handlerpublicvoiddispatchMessage(@NonNull Message msg){//callback在message的构造方法中初始化或者使用 handler.post(Runnable)时候才不为空 if(msg.callback != null){handleCallback(msg);}else{//mCallback是一个Callback对象,通过无参的构造方法创建出来的handler,该属性为null,此段不执行 if(mCallback != null){if(mCallback.handleMessage(msg)){return;}}handleMessage(msg);}}/*创建Message 可以直接new Message 但是有更好的方式 Message.obtain。因为可以检查是否有可以复用的Message,避免过多的创建、销毁Message对象达到优化内存和性能的目地
*///Messagepublicstatic Message obtain(Handler h){//调用重载的obtain方法Message m =obtain();//绑定创建Message对象的handlerm.target = h;return m;}//Messagepublicstatic Message obtain(){//sPoolSync是一个Object对象,用来同步保证线程安全synchronized(sPoolSync){//sPool是就是handler dispatchMessage 后,通过recycleUnchecked 回收用以复用的Message if(sPool != null){Message m = sPool;sPool = m.next;m.next = null;m.flags =0;//清除正在使用标志sPoolSize--;return m;}}returnnewMessage();}/*
Handler发送消息,sendMessage(Message)调用sendMessageDelayed,继续调用sendMessageAtTime,继续调用enqueueMessage,继续调用messageQueue的enqueueMessage方法,将消息保存在了消息队列中,而最终由 Looper取出,交给Handler的dispatchMessage进行处理
*///handlerpublicfinalbooleansendMessageDelayed(@NonNull Message msg,long delayMillis){if(delayMillis <0){delayMillis =0;}returnsendMessageAtTime(msg, SystemClock.uptimeMillis()+ delayMillis);}//handlerpublicbooleansendMessageAtTime(@NonNull Message msg,long uptimeMillis){MessageQueue queue = mQueue;if(queue == null){RuntimeException e =newRuntimeException(this+" sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);returnfalse;}returnenqueueMessage(queue, msg, uptimeMillis);}/*
Message和Handler的绑定
创建Message的时候可以通过 Message.obtain(Handler h) 这个构造方法绑定。
当然可以在Handler 中的 enqueueMessage()绑定了,所有发送Message的方法都会调用此方法入队,所以在创建Message的时候是可以不绑定的
*///handlerprivatebooleanenqueueMessage(MessageQueue queue, Message msg,long uptimeMillis){msg.target =this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if(mAsynchronous){msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}/*
Handler机制里面最主要的类MessageQueue,这个类就是所有消息的存储仓库,在这个仓库中,我们如何的管理好消息,这个就是一个关键点了。
消息管理就2点:
1)消息入库(enqueueMessage)
2)消息出库(next),所以这两个接口是确保线程安全的主要档口
*///MessageQueuebooleanenqueueMessage(Message msg,long when){if(msg.target == null){thrownewIllegalArgumentException("Message must have a target.");}if(msg.isInUse()){thrownewIllegalStateException(msg +" This message is already in use.");}synchronized(this){if(mQuitting){IllegalStateException e =newIllegalStateException(msg.target +" sending message to a Handler on a dead thread");Log.w(TAG, e.getMessage(), e);msg.recycle();returnfalse;}msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;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{// Inserted within the middle of the queue. Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;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.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if(needWake){nativeWake(mPtr);}}returntrue;}//MessageQueue
Message next(){// 1.如果nextPollTimeoutMillis = -1,一直阻塞不会超时。 // 2.如果nextPollTimeoutMillis = 0,不会阻塞,立即返回。 // 3.如果nextPollTimeoutMillis > 0,最长阻塞nextPollTimeoutMillis毫秒(超时)//如果期间有程序唤醒会立即返回。 int nextPollTimeoutMillis =0;for(;;){//native的方法,在没有消息的时候回阻塞管道读取端,只有nativePollOnce返回之后才能往下执行//阻塞操作,等待nextPollTimeoutMillis时长nativePollOnce(ptr, nextPollTimeoutMillis);synchronized(this){// Try to retrieve the next message. Return if found.finallong now = SystemClock.uptimeMillis();Message prevMsg = null;Message msg = mMessages;//如果target==null,那么它就是屏障,需要循环遍历,一直往后找到第一个异步的消息if(msg != null && msg.target == null){// Stalled by a barrier. Find the next asynchronous message in the queue.do{prevMsg = msg;msg = msg.next;}while(msg != null &&!msg.isAsynchronous());}if(msg != null){if(now < msg.when){// Next message is not ready. Set a timeout to wake up when it is ready.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();return msg;}}else{// No more messages.nextPollTimeoutMillis =-1;}}// 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 handlerboolean 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;}}//handlerprivatestaticvoidhandleCallback(Message message){message.callback.run();}/*
在handleMessage(Message)方法中,我们可以拿到message对象,根据不同的需求进行处理,整个Handler机制的流程就结束了
*//*
next函数:从线程里面取消息,而且每次都是队列的头部取,那么它加锁是不是没有意义呢?答案是否定的,我们必须要在next里面加锁,由于synchronized(this)作用范围是所有 this正在访问的代码块都会有保护作用,它可以保证 next函数和 enqueueMessage函数能够实现互斥。这样才能真正的保证多线程访问的时候MessageQueue 的有序进行。
*//*
postSyncBarrier()
同步屏障:阻碍同步消息,只让异步消息通过。
*///MessageQueueprivateintpostSyncBarrier(long when){// Enqueue a new sync barrier token.// We don't need to wake the queue because the purpose of a barrier is to stall it.synchronized(this){finalint token = mNextBarrierToken++;//从消息池中获取Messagefinal Message msg = Message.obtain();msg.markInUse();//初始化Message对象的时候,并没有给target赋值,因此 target==nullmsg.when = when;msg.arg1 = token;Message prev = null;Message p = mMessages;if(when !=0){while(p != null && p.when <= when){prev = p;p = p.next;}}if(prev != null){// invariant: p == prev.nextmsg.next = p;prev.next = msg;}else{msg.next = p;mMessages = msg;}return token;}}/*
Message 对象初始化的时候并没有给 target 赋值,因此,target == null 的来源就找到了。上面消息的插入也做了相应的注释。
target == null 的消息就进入了消息队列
*//*
当消息队列开启同步屏障的时候(即标识为 msg.target == null),消息机制在处理消息的时候,优先处理异步消息。
这样,同步屏障就起到了一种过滤和优先级的作用
*///Looperpublicvoidquit(){mQueue.quit(false);}//LooperpublicvoidquitSafely(){mQueue.quit(true);}/*
这两个函数是调用的MessageQueue的quit()。
*///MessageQueuevoidquit(boolean safe){if(!mQuitAllowed){thrownewIllegalStateException("Main thread not allowed to quit.");}synchronized(this){if(mQuitting){return;}mQuitting =true;if(safe){removeAllFutureMessagesLocked();}else{removeAllMessagesLocked();}//native的方法,在没有消息的时候回阻塞管道读取端,只有nativePollOnce返回之后才能往下执行//阻塞操作,等待nextPollTimeoutMillis时长//通过向管道mWakeEventFd写入值来标志唤醒信号// We can assume mPtr != 0 because mQuitting was previously false.nativeWake(mPtr);}}/*
remove消息,释放内存
*///MessageQueueprivatevoidremoveAllFutureMessagesLocked(){finallong 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);}}}