乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      android消息處理源碼分析

       路人甲Java 2022-01-16

      一、簡介
      消息處理機(jī)制主要涉及到這幾個(gè)類:
      1.Looper
      2.MessageQueue
      3.Message
      4.Handler

       

      二、源碼分析

      Looper.class的關(guān)鍵源碼:

       

      //保存Looper對(duì)象,在android中每創(chuàng)建一個(gè)消息隊(duì)列,就有一個(gè)并且是唯一一個(gè)與之對(duì)應(yīng)的Looper對(duì)象 
      static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
      //主線程的Looper
      private static Looper sMainLooper;
      //消息隊(duì)列
      final MessageQueue mQueue;
      final Thread mThread;
      
      //子線程中通過調(diào)用該方法來創(chuàng)建消息隊(duì)列
      public static void prepare() {
          prepare(true);
      }
      
      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));
      }
      
      
      //主線程調(diào)用該方法來創(chuàng)建消息隊(duì)列
      public static void prepareMainLooper() {
          prepare(false);
          synchronized (Looper.class) {
              if (sMainLooper != null) {
                  throw new IllegalStateException("The main Looper has already been prepared.");
              }
              sMainLooper = myLooper();
          }
      }
      
      //實(shí)例化Looper,創(chuàng)建消息隊(duì)列,獲取當(dāng)前線程
      private Looper(boolean quitAllowed) {
          mQueue = new MessageQueue(quitAllowed);
          mThread = Thread.currentThread();
      }
      
      //調(diào)用loop方法開啟消息循環(huán) 
      public static void loop() { 
          //獲取當(dāng)前的Looper對(duì)象,若為null,拋出異常 
          final Looper me = myLooper();
          if (me == null) {
              throw new RuntimeException("No Looper; Looper.prepare() 
                  wasn't called on this thread."); 
           } 
          //獲取當(dāng)前的消息隊(duì)列,進(jìn)入循環(huán) 
          final MessageQueue queue = me.mQueue; 
          for (;;) { 
              //調(diào)用next()方法從消息隊(duì)列中獲取消息,如果為null,結(jié)束循環(huán);否則,繼續(xù)執(zhí)行(有可能會(huì)阻塞) 
              Message msg = queue.next(); 
              if (msg == null) { 
                  return; 
              } 
              ...... 
              try { 
                  //調(diào)用handler的dispatchMessage(msg)分發(fā)消息  
                  msg.target.dispatchMessage(msg); 
              } finally {
              ...... 
              } 
              //回收消息資源  
              msg.recycleUnchecked(); 
          }
      }
      
      //消息循環(huán)退出
      public void quit() {
          mQueue.quit(false);
      }
      
      public void quitSafely() {
          mQueue.quit(true);
      }

       

      消息循環(huán)退出過程

      從上面可以看到loop()方法是一個(gè)死循環(huán),只有當(dāng)MessageQueue的next()方法返回null時(shí)才會(huì)結(jié)束循環(huán)。那么MessageQueue的next()方法何時(shí)為null呢?

      在Looper類中我們看到了兩個(gè)結(jié)束的方法quit()和quitSalely()。
      兩者的區(qū)別就是quit()方法直接結(jié)束循環(huán),處理掉MessageQueue中所有的消息。
      quitSafely()在處理完消息隊(duì)列中的剩余的非延時(shí)消息(延時(shí)消息(延遲發(fā)送的消息)直接回收)時(shí)才退出。這兩個(gè)方法都調(diào)用了MessageQueue的quit()方法

       

      MessageQueue.class 的關(guān)鍵源碼:

      MessageQueue中最重要的就是兩個(gè)方法:
      1.enqueueMessage()向隊(duì)列中插入消息
      2.next() 從隊(duì)列中取出消息

      /*
      *MessageQueue中enqueueMessage方法的目的有兩個(gè):
      *1.插入消息到消息隊(duì)列
      *2.喚醒Looper中等待的線程(如果是即時(shí)消息并且線程是阻塞狀態(tài))
      */
      boolean enqueueMessage(Message msg, long when) {
          //發(fā)送該消息的handler為null,拋出異常
          if (msg.target == null) {
              throw new IllegalArgumentException("Message must have a target.");
          }
          //此消息正在被使用
          if (msg.isInUse()) {
              throw new IllegalStateException(msg + " This message is already in use.");
          }
      
          synchronized (this) {
              //此消息隊(duì)列已經(jīng)被放棄了
              if (mQuitting) {
                  IllegalStateException e = new IllegalStateException(
                          msg.target + " sending message to a Handler on a dead thread");
                  msg.recycle();
                  return false;
              }
              msg.markInUse();
              msg.when = when;
              //消息隊(duì)列的第一個(gè)元素,MessageQueue中的成員變量mMessages指向的就是該鏈表的頭部元素。
              Message p = mMessages;
              boolean needWake;
              if (p == null || when == 0 || when < p.when) {
                  //如果此隊(duì)列中頭部元素是null(空的隊(duì)列,一般是第一次),或者此消息不是延時(shí)的消息,則此消息需要被立即處理,
                  //將該消息作為新的頭部,并將此消息的next指向舊的頭部。如果是阻塞狀態(tài)則需要喚醒。
                  msg.next = p;
                  mMessages = msg;
                  needWake = mBlocked;
              } else {
                  //如果此消息是延時(shí)的消息,則將其添加到隊(duì)列中,
                  //原理就是鏈表的添加新元素,按照時(shí)間順序來插入的,這樣就得到一條有序的延時(shí)消息鏈表  
                  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;
                  prev.next = msg;
              }
              if (needWake) {
                  nativeWake(mPtr);
              }
          }
          return true;
      }
      
      Message next() {
          //與native方法相關(guān),當(dāng)mPtr為0時(shí)返回null,退出消息循環(huán)
          final long ptr = mPtr; 
          if (ptr == 0) {
              return null;
          }
      
          int pendingIdleHandlerCount = -1;
          //0不進(jìn)入睡眠,-1進(jìn)入睡眠 
          int nextPollTimeoutMillis = 0;  
          for (;;) {
              if (nextPollTimeoutMillis != 0) {
                  //處理當(dāng)前線程中待處理的Binder進(jìn)程間通信請(qǐng)求
                  Binder.flushPendingCommands();  
              }
              //native方法,nextPollTimeoutMillis為-1時(shí)進(jìn)入睡眠狀態(tài)
              //阻塞方法,主要是通過native層的epoll監(jiān)聽文件描述符的寫入事件來實(shí)現(xiàn)的。
              //如果nextPollTimeoutMillis=-1,一直阻塞不會(huì)超時(shí)。
              //如果nextPollTimeoutMillis=0,不會(huì)阻塞,立即返回。
              //如果nextPollTimeoutMillis>0,最長阻塞nextPollTimeoutMillis毫秒(超時(shí)),如果期間有程序喚醒會(huì)立即返回
              nativePollOnce(ptr, nextPollTimeoutMillis); 
              synchronized (this) {
                  final long now = SystemClock.uptimeMillis();
                  Message prevMsg = null;
                  Message msg = mMessages;
                  if (msg != null && msg.target == null) {
                      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 {
                          //正常取出消息,設(shè)置mBlocked = false代表目前沒有阻塞
                          mBlocked = false;
                          if (prevMsg != null) {
                              prevMsg.next = msg.next;
                          } else {
                              mMessages = msg.next;
                          }
                          msg.next = null;
                          msg.markInUse();
                          return msg;
                      }
                  } else {
                      // No more messages.更新到睡眠狀態(tài)
                      nextPollTimeoutMillis = -1;
                  }
      
                      // Process the quit message now that all pending messages have been handled.
                      if (mQuitting) {
                          dispose();
                          return null;
                      }
      
                      // If first time idle, then get the number of idlers to run.
                      // Idle handles only run if the queue is empty or if the first message
                      // in the queue (possibly a barrier) is due to be handled in the future.
                      if (pendingIdleHandlerCount < 0
                              && (mMessages == null || now < mMessages.when)) {
                          pendingIdleHandlerCount = mIdleHandlers.size();
                      }
                      if (pendingIdleHandlerCount <= 0) {
                          // No idle handlers to run.  Loop and wait some more.
                          mBlocked = true;
                          continue;
                      }
      
                      if (mPendingIdleHandlers == null) {
                          mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                      }
                      mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
                  }
              }            
              //非睡眠狀態(tài)下處理IdleHandler接口 
              for (int i = 0; i < pendingIdleHandlerCount; i++) { 
                  final IdleHandler idler = mPendingIdleHandlers[i]; 
                  // release the reference to the handler 
                  mPendingIdleHandlers[i] = null; 
                  boolean keep = false; 
                  try { 
                     keep = idler.queueIdle(); 
                  } catch (Throwable t) { 
                      Log.wtf(TAG, "IdleHandler threw exception", t); 
                  } 
                  if (!keep) { 
                      synchronized (this) { 
                          mIdleHandlers.remove(idler); 
                      } 
                  } 
              } 
              pendingIdleHandlerCount = 0; 
              nextPollTimeoutMillis = 0;
          }        
      }

       

      Handler.class源碼分析:

      /*
      *通過handler類向線程的消息隊(duì)列發(fā)送消息,
      *每個(gè)Handler對(duì)象中都有一個(gè)Looper對(duì)象和MessageQueue對(duì)象
      */
      public Handler(Callback callback, boolean async) {
          if (FIND_POTENTIAL_LEAKS) {
              final Class<? extends Handler> klass = getClass();
              if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                      (klass.getModifiers() & Modifier.STATIC) == 0) {
                  Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                      klass.getCanonicalName());
              }
          }
          //獲取Looper對(duì)象
          mLooper = Looper.myLooper(); 
          if (mLooper == null) {...}
          //獲取消息隊(duì)列
          mQueue = mLooper.mQueue;  
          mCallback = callback;
          mAsynchronous = async;
      }
      
      /*
      *多種sendMessage方法,最終都調(diào)用了同一個(gè)方法sendMessageAtTime()
      */
      public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
          MessageQueue queue = mQueue;
          if (queue == null) {
              RuntimeException e = new RuntimeException(
                      this + " sendMessageAtTime() called with no mQueue");
              Log.w("Looper", e.getMessage(), e);
              return false;
          }
          //向消息隊(duì)列中添加消息
          return enqueueMessage(queue, msg, uptimeMillis); 
      }
          
      /*
      *1.當(dāng)Message中的callback不為null時(shí),執(zhí)行Message中的callback中的方法。這個(gè)callback時(shí)一個(gè)Runnable接口。
      *2.當(dāng)Handler中的Callback接口不為null時(shí),執(zhí)行Callback接口中的方法。
      *3.直接執(zhí)行Handler中的handleMessage()方法。
      */
      public void dispatchMessage(Message msg) {
          // 消息Callback接口不為null,執(zhí)行Callback接口
          if (msg.callback != null) {
              handleCallback(msg);
          } else {
              if (mCallback != null) {
                  //Handler Callback接口不為null,執(zhí)行接口方法
                  if (mCallback.handleMessage(msg)) {
                      return;
                  }
              }
              //處理消息
              handleMessage(msg); 
          }
      }

       

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多