Android消息机制不完全解析(上) .

来源:互联网 发布:花生日记app淘宝 编辑:程序博客网 时间:2024/05/23 02:06
转自:http://blog.csdn.net/a220315410/article/details/9857225?utm_source=tuicool&utm_medium=referral

Handler和Message是Android开发者常用的两个API,我一直对于它的内部实现比较好奇,所以用空闲的时间,阅读了一下他们的源码。

   相关的Java Class:
  • android.os.Message
  • android.os.MessageQueue
  • android.os.Looper
  • android.os.Handler
    相关的C++ Class:
  • android.NativeMessageQueue
  • android.Looper
  • android.LooperCallback
  • android.SimpleLooperCallback
  • android.Message
  • android.MessageHandler
首先,来看看这些类之间的关系:


首先,让我们从相对简单的java实现开始看起:

Message

    Message类可以说是最简单的,主要提供了一些成员,用以保存消息数据。
[java] view plain copy print?
  1.  public int what;//用以表示消息类别  
  2.   
  3.  public int arg1;//消息数据  
  4.   
  5.  public int arg2;//消息数据  
  6.   
  7.  public Object obj;//消息数据  
  8.    
[java] view plain copy print?
  1. /*package*/ long when;//消息应该被处理的时间  
  2.   
  3. /*package*/ Bundle data;//消息数据  
  4.   
  5. /*package*/ Handler target;//处理这个消息的handler  
  6.   
  7. /*package*/ Runnable callback;//回调函数  
  8.   
  9. // sometimes we store linked lists of these things  
  10. /*package*/ Message next;//形成链表,保存Message实例  

    值得一提的是,Android提供了一个简单,但是有用的消息池,对于Message这种使用频繁的类型,可以有效的减少内存申请和释放的次数,提高性能。
[java] view plain copy print?
  1. private static final Object sPoolSync = new Object();  
  2. private static Message sPool;  
  3. private static int sPoolSize = 0;  
  4.   
  5. private static final int MAX_POOL_SIZE = 50;  

[java] view plain copy print?
  1. /** 
  2.  * Return a new Message instance from the global pool. Allows us to 
  3.  * avoid allocating new objects in many cases. 
  4.  */  
  5. public static Message obtain() {  
  6.     synchronized (sPoolSync) {  
  7.         if (sPool != null) {//消息池不为空,则从消息池中获取实例  
  8.             Message m = sPool;  
  9.             sPool = m.next;  
  10.             m.next = null;  
  11.             sPoolSize--;  
  12.             return m;  
  13.         }  
  14.     }  
  15.     return new Message();  
  16. }  
  17.   
  18. /** 
  19.  * Return a Message instance to the global pool.  You MUST NOT touch 
  20.  * the Message after calling this function -- it has effectively been 
  21.  * freed. 
  22.  */  
  23. public void recycle() {  
  24.     clearForRecycle();  
  25.   
  26.     synchronized (sPoolSync) {  
  27.         if (sPoolSize < MAX_POOL_SIZE) {//消息池大小未满,则放入消息池  
  28.             next = sPool;  
  29.             sPool = this;  
  30.             sPoolSize++;  
  31.         }  
  32.     }  
  33. }  
  34. /*package*/ void clearForRecycle() {  
  35.     flags = 0;  
  36.     what = 0;  
  37.     arg1 = 0;  
  38.     arg2 = 0;  
  39.     obj = null;  
  40.     replyTo = null;  
  41.     when = 0;  
  42.     target = null;  
  43.     callback = null;  
  44.     data = null;  
  45. }  

    小结:
  1. Message的核心在于它的数据域,Handler根据这些内容来识别和处理消息
  2. 应该使用Message.obtain(或者Handler.obtainMessage)函数获取message实例

Handler

    首先看看构造函数:

[java] view plain copy print?
  1. public interface Callback {  
  2.     public boolean handleMessage(Message msg);  
  3. }  

[java] view plain copy print?
  1. public Handler() {  
  2.     this(nullfalse);  
  3. }  
[java] view plain copy print?
  1. public Handler(Callback callback, boolean async) {  
  2.     if (FIND_POTENTIAL_LEAKS) {  
  3.         final Class<? extends Handler> klass = getClass();  
  4.         if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  5.                 (klass.getModifiers() & Modifier.STATIC) == 0) {  
  6.             Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  7.                 klass.getCanonicalName());  
  8.         }  
  9.     }  
  10.   
  11.     mLooper = Looper.myLooper();  
  12.     if (mLooper == null) {  
  13.         throw new RuntimeException(  
  14.             "Can't create handler inside thread that has not called Looper.prepare()");  
  15.     }  
  16.     mQueue = mLooper.mQueue;  
  17.     mCallback = callback; //使用Callback可以拦截Handler处理消息,之后会在dispatchMessage函数中,大展身手  
  18.     mAsynchronous = async;//设置handler的消息为异步消息,暂时先无视这个变量  
  19. }  

    Handler的构造函数最主要的就是初始化成员变量:mLooper和mQueue。 这边需要注意的一个问题是:Looper.myLooper()不能返回null,否则抛出RuntimeExeception。稍后详解Looper.myLooper();函数在何种情况下会抛出异常。


    Handler.obtainMessage系列的函数都会调用Message类中对应的静态方法,从消息池中获取一个可用的消息实例。典型实现如下:

[java] view plain copy print?
  1. public final Message obtainMessage()  
  2. {  
  3.     return Message.obtain(this);  
  4. }  


    Handler.post系列和send系列函数最终都会调用enqueueMessage函数,把message入列,不同之处在于post系列函数会以Runable参数构建一个Message实例。

[java] view plain copy print?
  1.  private static Message getPostMessage(Runnable r) {  
  2.     Message m = Message.obtain();  
  3.     m.callback = r;//一会我们会看到callback非空的message和callback为空的mesage在处理时的差异  
  4.     return m;  
  5. }  
  6.   
  7. public final boolean post(Runnable r)  
  8. {  
  9.    return  sendMessageDelayed(getPostMessage(r), 0);  
  10. }  
  11.   
  12. public final boolean sendMessage(Message msg)  
  13. {  
  14.     return sendMessageDelayed(msg, 0);  
  15. }  
  16.   
  17. public final boolean sendMessageDelayed(Message msg, long delayMillis)  
  18. {  
  19.     if (delayMillis < 0) {  
  20.         delayMillis = 0;  
  21.     }  
  22.     return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);  
  23. }  
  24.   
  25. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {  
  26.     MessageQueue queue = mQueue;  
  27.     if (queue == null) {  
  28.         RuntimeException e = new RuntimeException(  
  29.                 this + " sendMessageAtTime() called with no mQueue");  
  30.         Log.w("Looper", e.getMessage(), e);  
  31.         return false;  
  32.     }  
  33.     return enqueueMessage(queue, msg, uptimeMillis);  
  34. }  
  35.   
  36. //最终都会调用这个函数,把message入列   
  37. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {  
  38.     msg.target = this;  
  39.     if (mAsynchronous) {  
  40.         msg.setAsynchronous(true);//Handler的<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mAsynchronous属性,决定了msg是否为asynchronous,稍后在MessageQueue.next函数中,可以看到</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">asynchronous对于消息处理的影响</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">  
  41. AN>        }  
  42.     return queue.enqueueMessage(msg, uptimeMillis);  
  43. }  
    除了这些之外,Handler还提供了hasMessage系列和removeMessages系列函数用以管理Handler对应的MessageQueue中的消息。


    接下来主角登场,Handler.dispatchMessage:

[java] view plain copy print?
  1. private static void handleCallback(Message message) {  
  2.     message.callback.run();  
  3. }  
  4. /** 
  5.  * Subclasses must implement this to receive messages. 
  6.  */  
  7. public void handleMessage(Message msg) {  
  8. }  
  9.   
  10. /** 
  11.  * Handle system messages here. 
  12.  */  
  13. public void dispatchMessage(Message msg) {  
  14.     if (msg.callback != null) {//message的callback不为null,则执行  
  15.         handleCallback(msg);  
  16.     } else {  
  17.         if (mCallback != null) {//如果Hanlder的mCallback成员不为null,则调用  
  18.             if (mCallback.handleMessage(msg)) {//如果handleMessage返回值为true,则拦截消息  
  19.                 return;  
  20.             }  
  21.         }  
  22.         handleMessage(msg);//处理消息   
  23.     }  
  24. }  

    注释应该比较清楚,不多说。 小结:

  1.  Handler类最为核心的函数是enqueueMessage和dispatcherMessage,前者把待处理的消息放入MessageQueue,而Looper调用后者来处理从MessageQueue获取的消息。
  2.  callback不为null(通过post系列函数添加到消息队列中)的message无法被拦截,而callback为null的函数可以被Handler的mCallback拦截


Looper

    同样从构造函数看起:
[java] view plain copy print?
  1. private Looper(boolean quitAllowed) {  
  2.     mQueue = new MessageQueue(quitAllowed);//每个Looper有一个MessageQueue  
  3.     mRun = true;  
  4.     mThread = Thread.currentThread();  
  5. }  
[java] view plain copy print?
  1.      ** Initialize the current thread as a looper.  
  2.       * This gives you a chance to create handlers that then reference  
  3.       * this looper, before actually starting the loop. Be sure to call  
  4.       * {@link #loop()} after calling this method, and end it by calling  
  5.       * {@link #quit()}.  
  6.       */  
  7.     public static void prepare() {  
  8.         prepare(true);//后台线程的looper都允许退出  
  9.     }  
  10.   
  11.     private static void prepare(boolean quitAllowed) {  
  12.         if (sThreadLocal.get() != null) {  
  13.             throw new RuntimeException("Only one Looper may be created per thread");//每个线程只能有一个Looper  
  14.         }  
  15.         sThreadLocal.set(new Looper(quitAllowed));//把实例保存到TLS(Thread Local Save),仅有每个线程访问自己的Looper  
  16.     }  
  17.   
  18.     /** 
  19.      * Initialize the current thread as a looper, marking it as an 
  20.      * application's main looper. The main looper for your application 
  21.      * is created by the Android environment, so you should never need 
  22.      * to call this function yourself.  See also: {@link #prepare()} 
  23.      */  
  24.     public static void prepareMainLooper() {  
  25.         prepare(false);//主线程的lopper不可以退出  
  26.         synchronized (Looper.class) {  
  27.             if (sMainLooper != null) {  
  28.                 throw new IllegalStateException("The main Looper has already been prepared.");  
  29.             }  
  30.             sMainLooper = myLooper();  
  31.         }  
  32.     }  
    因为是私有的构造函数,所以理论上来说只能通过prepare和prepareMainLooper两个函数来实例化Looper,但是google的注释也说的很清楚:prepareMainLooper()应该由系统调用(有兴趣的同学可以去看看AtivityThread类的main函数),所以,应用开发者可以使用的只剩下prepare函数。
    好了,Looper的实例是构造出来,但是如何获取构造出来的实例呢?
[java] view plain copy print?
  1. /** Returns the application's main looper, which lives in the main thread of the application. 
  2.  */  
  3. public static Looper getMainLooper() {  
  4.     synchronized (Looper.class) {  
  5.         return sMainLooper;  
  6.     }  
  7. }  
  8. /** 
  9.  * Return the Looper object associated with the current thread.  Returns 
  10.  * null if the calling thread is not associated with a Looper. 
  11.  */  
  12. public static Looper myLooper() {  
  13.     return sThreadLocal.get();  
  14. }  
     现在,我们应该知道如何防止Handler实例化的时候,抛出RuntimeException:在守护线程中实例化Handler之前,需要先调用Looper.perpare函数来构造Looper实例。

     然后,重头戏来了: 
[java] view plain copy print?
  1.     /** 
  2.      * Quits the looper. 
  3.      * 
  4.      * Causes the {@link #loop} method to terminate as soon as possible. 
  5.      */  
  6.     public void quit() {  
  7.         mQueue.quit();  
  8.     }  
  9.   
  10.     /** 
  11.      * Run the message queue in this thread. Be sure to call 
  12.      * {@link #quit()} to end the loop. 
  13.      */  
  14.     public static void loop() {  
  15.         final Looper me = myLooper();  
  16.         if (me == null) {//调用looper之前,需要先调用perpare,否则您懂的...  
  17.             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  18.         }  
  19.         final MessageQueue queue = me.mQueue;  
  20.   
  21.         // Make sure the identity of this thread is that of the local process,  
  22.         // and keep track of what that identity token actually is.  
  23.         Binder.clearCallingIdentity();//不太明白这个函数,但不是重点可以无视  
  24.         final long ident = Binder.clearCallingIdentity();  
  25.   
  26.         for (;;) {  
  27.             Message msg = queue.next(); // might block 获取一个下一个消息,如果当前没有要处理的消息,则block,之后我们会看到这个API的实现  
  28.             if (msg == null) {//调用了MessgeQueu的quit函数后,MessageQueue.next会返回null  
  29.                 // No message indicates that the message queue is quitting.  
  30.                 return;  
  31.             }  
  32.   
  33.             // This must be in a local variable, in case a UI event sets the logger  
  34.             Printer logging = me.mLogging;  
  35.             if (logging != null) {//借助logging我们可以打印Looper中处理的消息  
  36.                 logging.println(">>>>> Dispatching to " + msg.target + " " +  
  37.                         msg.callback + ": " + msg.what);  
  38.             }  
  39.   
  40.             msg.target.dispatchMessage(msg);//调用handler处理消息  
  41.   
  42.             if (logging != null) {  
  43.                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
  44.             }  
  45.   
  46.             // Make sure that during the course of dispatching the  
  47.             // identity of the thread wasn't corrupted.  
  48.             final long newIdent = Binder.clearCallingIdentity();//选择性无视  
  49.             if (ident != newIdent) {  
  50.                 Log.wtf(TAG, "Thread identity changed from 0x"  
  51.                         + Long.toHexString(ident) + " to 0x"  
  52.                         + Long.toHexString(newIdent) + " while dispatching to "  
  53.                         + msg.target.getClass().getName() + " "  
  54.                         + msg.callback + " what=" + msg.what);  
  55.             }  
  56.   
  57.             msg.recycle();//回收消息到消息池   
  58.         }  
  59.     }  
    Looper.loop()函数是Looper类的核心函数,主要循环进行两个操作:
  1. 从MessageQueue中获取一个消息,当前没有消息需要处理时,则block
  2. 调用message的Handler(target)处理消息
    基本上,我们可以把Looper理解为一个死循环,Looper开始work以后,线程就进入了以消息为驱动的工作模型。

    小结:
  1. 每个线程最多可以有一个Looper。
  2. 每个Looper有且仅有一个MessageQueue
  3. 每个Handler关联一个MessageQueue,由该MessageQueue关联的Looper执行(调用Hanlder.dispatchMessage)
  4. 每个MessageQueue可以关联任意多个Handler
  5. Looper API的调用顺序:Looper.prepare >> Looper.loop >> Looper.quit
  6. Looper的核心函数是Looper.loop,一般loop不会返回,直到线程退出,所以需要线程完成某个work时,请发送消息给Message(或者说Handler)

MessageQueue

    
    MessageQueue类是唯一包含native函数的类,我们先大致看一下,稍后C++的部分在详细解释:
[java] view plain copy print?
  1. private native void nativeInit();    //初始化  
  2. private native void nativeDestroy(); //销毁  
  3. private native void nativePollOnce(int ptr, int timeoutMillis); //等待<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">timeoutMillis指定的时间</SPAN>  
  4. private native void nativeWake(int ptr);//唤醒<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">nativePollOnce的等待</SPAN>  

    然后,我们再从构造函数看起:
[java] view plain copy print?
  1.   
  2. Message mMessages;//数据域mMessages的类型虽然是Message,但是因为Message.next数据域的原因,其实mMessage是链表的第一个元素  
  3.   
  4. MessageQueue(boolean quitAllowed) {  
  5.     mQuitAllowed = quitAllowed;  
  6.     nativeInit();//初始化nativeMessageQueue   
  7. }  
    对应的,在销毁的时候:
[java] view plain copy print?
  1. @Override  
  2. protected void finalize() throws Throwable {  
  3.     try {  
  4.         nativeDestroy();//销毁nativeMessageQueue   
  5.     } finally {  
  6.         super.finalize();  
  7.     }  
  8. }  
    
    此外,MessageQueue提供了一组函数(e.g. hasMessage, removeMessage)来查询和移除待处理的消息,我们在前面的Handler类上看到的对应函数的实现就是调用这组函数。

    接下来,看看enqueueMessage函数,Handler函数就是调用这个函数把message放到MessageQueue中:
[java] view plain copy print?
  1.     final boolean enqueueMessage(Message msg, long when) {  
  2.         if (msg.isInUse()) {//检查msg是否在使用中,一会我们可以看到MessageQueue.next()在返回前通过Message.makeInUse函数设置msg为使用状态,而我们之前看到过Looper.loop中通过调用调用Message.recycle(),把Message重置为未使用的状态。  
  3.             throw new AndroidRuntimeException(msg + " This message is already in use.");  
  4.         }  
  5.         if (msg.target == null) {//msg必须知道由那个Handler负责处理它  
  6.             throw new AndroidRuntimeException("Message must have a target.");  
  7.         }  
  8.   
  9.         boolean needWake;  
  10.         synchronized (this) {  
  11.             if (mQuiting) {//如果已经调用MessageQueue.quit,那么不再接收新的Message  
  12.                 RuntimeException e = new RuntimeException(  
  13.                         msg.target + " sending message to a Handler on a dead thread");  
  14.                 Log.w("MessageQueue", e.getMessage(), e);  
  15.                 return false;  
  16.             }  
  17.   
  18.             msg.when = when;  
  19.             Message p = mMessages;  
  20.             if (p == null || when == 0 || when < p.when) {//插到列表头  
  21.                 // New head, wake up the event queue if blocked.  
  22.                 msg.next = p;  
  23.                 mMessages = msg;  
  24.                 needWake = mBlocked;//当前MessageQueue处于block状态,所以需要唤醒  
  25.             } else {  
  26.                 // Inserted within the middle of the queue.  Usually we don't have to wake  
  27.                 // up the event queue unless there is a barrier at the head of the queue  
  28.                 // and the message is the earliest asynchronous message in the queue.  
  29.                 needWake = mBlocked && p.target == null && msg.isAsynchronous();//当且仅当MessageQueue因为Sync Barrier而block,并且msg为异步消息时,唤醒。 关于msg.isAsyncChronous(),请回去看看Handler.enqueueMessage函数和构造函数  
  30.                 Message prev;  
  31.                 for (;;) {<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">// 根据when的大小顺序,插入到合适的位置</SPAN>  
  32.                     prev = p;  
  33.                     p = p.next;  
  34.                     if (p == null || when < p.when) {  
  35.                         break;  
  36.                     }  
  37.                     if (needWake && p.isAsynchronous()) {//如果在插入位置以前,发现异步消息,则不需要唤醒  
  38.                         needWake = false;  
  39.                     }  
  40.                 }  
  41.                 msg.next = p; // invariant: p == prev.next  
  42.                 prev.next = msg;  
  43.             }  
  44.         }  
  45.         if (needWake) {  
  46.             nativeWake(mPtr);//唤醒nativeMessageQueue   
  47.         }  
  48.         return true;  
  49.     }  
  50.    
  51.     final void quit() {  
  52.         if (!mQuitAllowed) {//UI线程的Looper消息队列不可退出  
  53.             throw new RuntimeException("Main thread not allowed to quit.");  
  54.         }  
  55.   
  56.   
  57.         synchronized (this) {  
  58.             if (mQuiting) {  
  59.                 return;  
  60.             }  
  61.             mQuiting = true;  
  62.         }  
  63.         nativeWake(mPtr);//唤醒nativeMessageQueue  
  64.     }  
    关于sync barrier,再补充点解释: sync barrier是起到了一个阻塞器的作用,它可以阻塞when>它(即执行时间比它晚)的同步消息的执行,但不影响异步消息。sync barrier的特征是targe为null,所以它只能被remove,无法被执行。MessageQueue提供了下面两个函数来控制MessageQueue中的sync barrier(如何觉得sync barrier和异步消息难以理解的话,选择性无视就好,因为它们不妨碍我们理解Android消息机制的原理):
[java] view plain copy print?
  1. final int enqueueSyncBarrier(long when) {  
  2.     // Enqueue a new sync barrier token.   
  3.     // We don't need to wake the queue because the purpose of a barrier is to stall it.  
  4.     synchronized (this) {  
  5.         final int token = mNextBarrierToken++;  
  6.         final Message msg = Message.obtain();  
  7.         msg.arg1 = token;  
  8.   
  9.         Message prev = null;  
  10.         Message p = mMessages;  
  11.         if (when != 0) {  
  12.             while (p != null && p.when <= when) {  
  13.                 prev = p;  
  14.                 p = p.next;  
  15.             }  
  16.         }  
  17.         if (prev != null) { // invariant: p == prev.next  
  18.             msg.next = p;  
  19.             prev.next = msg;  
  20.         } else {  
  21.             msg.next = p;  
  22.             mMessages = msg;  
  23.         }  
  24.         return token;  
  25.     }  
  26. }  
  27.   
  28. final void removeSyncBarrier(int token) {  
  29.     // Remove a sync barrier token from the queue.  
  30.     // If the queue is no longer stalled by a barrier then wake it.  
  31.     final boolean needWake;  
  32.     synchronized (this) {  
  33.         Message prev = null;  
  34.         Message p = mMessages;  
  35.         while (p != null && (p.target != null || p.arg1 != token)) {  
  36.             prev = p;  
  37.             p = p.next;  
  38.         }  
  39.         if (p == null) {  
  40.             throw new IllegalStateException("The specified message queue synchronization "  
  41.                     + " barrier token has not been posted or has already been removed.");  
  42.         }  
  43.         if (prev != null) {  
  44.             prev.next = p.next;  
  45.             needWake = false;  
  46.         } else {  
  47.             mMessages = p.next;  
  48.             needWake = mMessages == null || mMessages.target != null;//其实我觉得这边应该是needWake = mMessages != null && mMessages.target != null  
  49.         }  
  50.         p.recycle();  
  51.     }  
  52.     if (needWake) {  
  53.         nativeWake(mPtr);//有需要的话,唤醒nativeMessageQueue  
  54.     }  
  55. }  

    重头戏又来了:
[java] view plain copy print?
  1. final Message next() {  
  2.       int pendingIdleHandlerCount = -1// -1 only during first iteration  
  3.       int nextPollTimeoutMillis = 0;  
  4.   
  5.       for (;;) {  
  6.           if (nextPollTimeoutMillis != 0) {  
  7.               Binder.flushPendingCommands();//不太理解,选择性无视  
  8.           }  
  9.           nativePollOnce(mPtr, nextPollTimeoutMillis);//等待nativeMessageQueue返回,最多等待nextPollTimeoutMillis毫秒  
  10.   
  11.           synchronized (this) {  
  12.               if (mQuiting) {//如果要退出,则返回null  
  13.                   return null;  
  14.               }  
  15.   
  16.               // Try to retrieve the next message.  Return if found.  
  17.               final long now = SystemClock.uptimeMillis();  
  18.               Message prevMsg = null;  
  19.               Message msg = mMessages;  
  20.               if (msg != null && msg.target == null) {//下一个消息为sync barrier  
  21.                   // Stalled by a barrier.  Find the next asynchronous message in the queue.  
  22.                   do {  
  23.                       prevMsg = msg;  
  24.                       msg = msg.next;  
  25.                   } while (msg != null && !msg.isAsynchronous());//因为存在sync barrier,仅有异步消息可以执行,所以寻在最近的异步消息  
  26.               }  
  27.               if (msg != null) {  
  28.                   if (now < msg.when) {  
  29.                       // Next message is not ready.  Set a timeout to wake up when it is ready.  
  30.                       nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);//消息还没到执行的时间,所以我们继续等待msg.when - now毫秒  
  31.                   } else {  
  32.                       // Got a message.   
  33.                       mBlocked = false;//开始处理消息了,所以不再是blocked状态  
  34.                       if (prevMsg != null) {  
  35.                           prevMsg.next = msg.next;//从链表中间移除message  
  36.                       } else {  
  37.                           mMessages = msg.next;//从链表头移除message  
  38.                       }  
  39.                       msg.next = null;  
  40.                       if (false) Log.v("MessageQueue""Returning message: " + msg);  
  41.                       msg.markInUse();//标记msg正在使用  
  42.                       return msg;//返回到Looper.loop函数  
  43.                   }  
  44.               } else {  
  45.                   // No more messages.   
  46.                   nextPollTimeoutMillis = -1;//没有消息可以处理,所以无限制的等待  
  47.               }  
  48.   
  49.               // If first time idle, then get the number of idlers to run.  
  50.               // Idle handles only run if the queue is empty or if the first message  
  51.               // in the queue (possibly a barrier) is due to be handled in the future.  
  52.               if (pendingIdleHandlerCount < 0  
  53.                       && (mMessages == null || now < mMessages.when)) {<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">// 目前无消息可以处理,可以执行IdleHandler</SPAN>  
  54.                   pendingIdleHandlerCount = mIdleHandlers.size();  
  55.               }  
  56.               if (pendingIdleHandlerCount <= 0) {  
  57.                   // No idle handlers to run.  Loop and wait some more.  
  58.                   mBlocked = true;  
  59.                   continue;  
  60.               }  
  61.   
  62.               if (mPendingIdleHandlers == null) {  
  63.                   mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];  
  64.               }  
  65.               mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);  
  66.           }  
  67.   
  68.           // Run the idle handlers.   
  69.           // We only ever reach this code block during the first iteration.  
  70.           for (int i = 0; i < pendingIdleHandlerCount; i++) {  
  71.               final IdleHandler idler = mPendingIdleHandlers[i];  
  72.               mPendingIdleHandlers[i] = null// release the reference to the handler  
  73.   
  74.               boolean keep = false;  
  75.               try {  
  76.                   keep = idler.queueIdle();  
  77.               } catch (Throwable t) {  
  78.                   Log.wtf("MessageQueue""IdleHandler threw exception", t);  
  79.               }  
  80.   
  81.               if (!keep) {  
  82.                   synchronized (this) {  
  83.                       mIdleHandlers.remove(idler);  
  84.                   }  
  85.               }  
  86.           }  
  87.   
  88.           // Reset the idle handler count to 0 so we do not run them again.  
  89.           pendingIdleHandlerCount = 0;//Looper.looper调用一次MessageQueue.next(),只允许调用一轮IdleHandler  
  90.   
  91.           // While calling an idle handler, a new message could have been delivered  
  92.           // so go back and look again for a pending message without waiting.  
  93.           nextPollTimeoutMillis = 0;//因为执行IdleHandler的过程中,可能有新的消息到来,所以把等待时间设置为0  
  94.       }  
  95.   }  
              为了方便大家理解Message的工作原理,先简单描述nativeWake,和natePollonce的作用:
  1. nativePollOnce(mPtr, nextPollTimeoutMillis);暂时无视mPtr参数,阻塞等待nextPollTimeoutMillis毫秒的时间返回,与Object.wait(long timeout)相似
  2. nativeWake(mPtr);暂时无视mPtr参数,唤醒等待的nativePollOnce函数返回的线程,从这个角度解释nativePollOnce函数应该是最多等待nextPollTimeoutMillis毫秒

    小结:
  1. MessageQueue作为一个容器,保存了所有待执行的消息。
  2. MessageQueue中的Message包含三种类型:普通的同步消息,Sync barrier(target = null),异步消息(isAsynchronous() = true)。
  3. MessageQueue的核心函数为enqueueMessage和next,前者用于向容器内添加Message,而Looper通过后者从MessageQueue中获取消息,并实现无消息情况下的等待。
  4. MessageQueue把Android消息机制的Java实现和C++实现联系起来。
    本来我是想一口气把java实现和C++实现都写完的,但是,无奈最近工作和个人事务都比较多,稍后为大家奉上C++实现的解析。
    
0 0
原创粉丝点击