0
点赞
收藏
分享

微信扫一扫

Android 消息机制之 MessageQueue.next() 消息取出的深入源码分析 [ 八 ]

Android 消息机制深入源码分析 [ 一 ]
Android 消息机制之 ThreadLocal 深入源码分析 [ 二 ]
Android 消息机制之 Looper 深入源码分析 [ 三 ]
Android 消息机制之 Message 与消息对象池的深入源码分析 [ 四 ]
Android 消息机制之 MessageQueue 深入源码分析 [ 五 ]
Android 消息机制之初识Handler [ 六 ]
Android 消息机制之 Handler 发送消息的深入源码分析 [ 七 ]
Android 消息机制之 MessageQueue.next() 消息取出的深入源码分析 [ 八 ]
Android 消息机制之消息的其他处理深入源码分析 [ 九 ]
Android 消息机制总结 [ 十 ]

紧接上一章消息的发送, 本章内容为消息的取出分析学习.

消息的取出主要是通过 Looperloop 方法. 这个方法在第三章的时候已经分析过, 分为以下几步

  1. 获取Looper对象
  2. 获取MessageQueue消息队列对象
  3. 死循环遍历
  4. 通过queue.next()来从MessageQueue的消息队列中获取一个Message msg对象
  5. 通过msg.target,dispatchMessage(msg)来处理消息
  6. 通过msg.recycleUnchecked() 方法来回收Message到消息对象池中.

其中 Message.recycleUnchecked() 在第四章的时候已经分析过, 那么现在就剩下 MessageQueue.next()handler.dispatchMessage() . 那么先来看 MessageQueue.next()

1. MessageQueue.next()

MessageQueue.java 310 行, 代码过多, 将分段分析.

Message next() {
  //分析 1
  final long ptr = mPtr;
  if (ptr == 0) {
      return null;
  }
  //分析 2
  int pendingIdleHandlerCount = -1; // -1 only during first iteration
  //分析 3
  int nextPollTimeoutMillis = 0;
  • 分析:
 //分析 4
  for (;;) {
      //分析 5
      if (nextPollTimeoutMillis != 0) {
          Binder.flushPendingCommands();
      }
      //分析 6
      nativePollOnce(ptr, nextPollTimeoutMillis);
      //分析 7
      synchronized (this) {
          final long now = SystemClock.uptimeMillis();
          Message prevMsg = null;
          Message msg = mMessages;
          //分析 8
          if (msg != null && msg.target == null) {
              do {
                  prevMsg = msg;
                  msg = msg.next;
              } while (msg != null && !msg.isAsynchronous());
          }
  • 分析
          //分析 9
          if (msg != null) {
              //分析 10
              if (now < msg.when) {
                  nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
              } else { //分析 11
                  mBlocked = false;
                  //分析 12
                  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 {
              //分析 13
              nextPollTimeoutMillis = -1;
          }
  • 分析

          //分析 14
          if (mQuitting) {
              dispose();
              return null;
          }
          //分析 15
          if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
              pendingIdleHandlerCount = mIdleHandlers.size();
          }
          //分析 16
          if (pendingIdleHandlerCount <= 0) {
              // No idle handlers to run.  Loop and wait some more.
              mBlocked = true;
              continue;
          }
          //分析 17
          if (mPendingIdleHandlers == null) {
              mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
          }
          mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
      }

注意: 当代码开始执行这里的时候, msg 要么为 null, 要么未到执行时间.

  • 分析
      //分析18
      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);
              }
          }
      }
      //分析 19
      pendingIdleHandlerCount = 0;
      //分析 20
      nextPollTimeoutMillis = 0;
  }
}

注意: 执行到这里, 说明目前没有可执行的 Message, 但是有可以在空闲时执行的 IdleHandler.

 
关于分析 18 的疑问. 为什么只会在第一次循环的时候会执行这里呢.


 
总结
总的来说当在 Looper.loop() 方法的死循环内, 调用MessageQueue.next() 方法获取一个 Message 的时候, 大致会分为以下几步.


好了, 本章分析学习就到这里结束了, 下一章将会分析学习 消息分发处理, 消息的移除, 以及消息的其他操作.

举报

相关推荐

0 条评论