美文网首页
Handler消息传递机制解析

Handler消息传递机制解析

作者: 钦_79f7 | 来源:发表于2019-12-20 16:30 被阅读0次

    Handler工作过程简述

    以主线程为例,从APP创建主线程开始,就为主线程创建了一个不可退出的looper,通过getMainLooper()可以获得其对象,以及有了一个looper相对应的队列mQueue,然后主线程中所有的handler,都是通过此唯一的looper进行分发派送消息,所有的msg,也都是依次排列在此唯一的mQueue中,等待looper进行接收分发。由于mQueue中的msg是依次出队的,所以在Activity onCreate()中执行View的post操作可以相应的达到一定的延迟作用。

    Looper

    Fields

    1. ThreadLocal<Looper> sThreadLocal:保存当前线程的本地变量,保证一个线程只有looper对象存在;
    2. Looper sMainLooper:UI线程的looper对象;
    3. MessageQueue mQueue:当前looper对应的消息队列;
    4. Thread mThread:记录当前处于的线程对象;

    Methods

    1. quit()/quitSafely():用于退出当前looper循环(仅仅在子线程中的looper有效,主线程的looper创建之初就不可以退出循环),其内部是调用的mQueue的quit(boolen)方法,mQueue的mQuitAllowed属性记录着当前looper对象是否允许退出循环操作;

      public void quit() {
          mQueue.quit(false);
      }
       public void quitSafely() {
          mQueue.quit(true);
      }
      
    2. static Looper getMainLooper():获取主线程的looper对象;

    3. public static void prepare():子线程中调用,创建子线程的looper(并且允许退出循环);

    4. public static @Nullable Looper myLooper():获取当前线程的looper;

    5. public static @NonNull MessageQueue myQueue():获取当前线程的消息队列;

    6. public @NonNull Thread getThread():获取looper的线程对象;

    7. public boolean isCurrentThread():判断当前线程与looper对应的线程是否一致;

    8. public static void loop():循环接收消息,通过mQueue.next()来不停获取下一个msg,并根据msg.target进行消息的分发,msg.target是当前handler对象,调用handler.dispatchMessage(msg)将此msg交给handler处理。

    MessageQueue

    Fields

    1. private final boolean mQuitAllowed:是否允许looper退出循环;

    Methods

    1. boolean enqueueMessage(Message msg, long when):将消息压入队列中,判断当前队列中是否有消息,没有则处于队首;或者根据msg.when来确定此msg是否要排在队首,还在插在队列中间某个位置;

      boolean enqueueMessage(Message msg, long when) {
          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) {
              if (mQuitting) {
                  IllegalStateException e = new IllegalStateException(
                          msg.target + " sending message to a Handler on a dead thread");
                  Log.w(TAG, e.getMessage(), e);
                  msg.recycle();
                  return false;
              }
      
              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作为队首
                  //或者当前队首的时间when大于msg的when时,msg成为新的队首
                  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;
                  //遍历队列,根据when来决定msg插入到队列的位置
                  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.next
                  prev.next = msg;
              }
      
              // We can assume mPtr != 0 because mQuitting is false.
              if (needWake) {
                  nativeWake(mPtr);
              }
          }
          return true;
      }
      
    2. Message next():返回队列中的下一个msg,其中msg的异步性,也是在此段代码中体现的;

      Message next() {
          ......
          
          for (;;) {
              if (nextPollTimeoutMillis != 0) {
                  Binder.flushPendingCommands();
              }
      
              nativePollOnce(ptr, nextPollTimeoutMillis);
      
              synchronized (this) {
                  // Try to retrieve the next message.  Return if found.
                  final long now = SystemClock.uptimeMillis();
                  Message prevMsg = null;
                  Message msg = mMessages;
                  if (msg != null && msg.target == null) {
                      //msg满足上述判断条件后,就会在队列中遍历msg,优先将异步的msg出列,
                      // Stalled by a barrier.  Find the next asynchronous message in the queue.
                      do {
                          prevMsg = msg;
                          msg = msg.next;
                          //此循环直到得到异步的msg才会退出循环
                      } while (msg != null && !msg.isAsynchronous());
                      
                  }
                  //非异步msg的出列
                  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;
                  }
      
                ......
          }
      }
      
    3. void quit(boolean safe):提供给looper退出循环的方法(原理:调用此方法后当前队列会返回一个null的msg,looper接收到null的msg后就执行退出循环的操作);

    Message

    Fields

    1. public int what:一般用于区分不同的msg;

    2. public int arg1,arg2:传递int数据;

    3. public Object obj:传递对象;

    4. Handler target:标记此msg需要发送给哪个handler去处理;

    5. long when:用于决定其在消息队列中的位置;

    6. Runnable callback:handler post方法系列的run回调对象;

    7. Bundle data:将数据存储到bundle中进行传递;

    8. int flags:用于标记当前msg处于什么状态

      1. FLAG_IN_USE:msg正在使用中;
      2. FLAG_ASYNCHRONOUS:异步处理此msg,,在MQueue中会优先让异步的msg出列;
      3. FLAGS_TO_CLEAR_ON_COPY_FROM:?
    9. private static final int MAX_POOL_SIZE = 50;默认消息池的大小为50;

    10. public Messenger replyTo:???

    11. Message next:用于记录当前msg的下一个msg是哪个,消息队列的实质就是通过此属性,使得所有msg之间形成一个链表的关系,这就是消息队列的存在形式,MessageQueue就是管理这个队列的类(入队,出队,退出等操作)

    Methods

    1. public static Message obtain():消息池中获取一个msg
    2. public void recycle():回收msg;

    Handler

    Fields

    1. final Looper mLooper:要创建一个handler对象,必须要为其设置looper;
    2. final MessageQueue mQueue:looper对应的消息队列;
    3. final Callback mCallback:handler处理消息的回调(public boolean handleMessage(Message msg),,通过设置此回调是handler处理msg的方式之一);

    Methods

    1. public final boolean post(Runnable r);
    2. public final boolean postAtTime(Runnable r, long uptimeMillis);
    3. public final boolean postDelayed(Runnable r, long delayMillis);
    4. public final boolean sendMessage(Message msg);
    5. public boolean sendMessageAtTime(Message msg, long uptimeMillis):handler发送消息最终都会调用到此方法,内部通过私有方法enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis),再通过mQueue.enqueueMessage(msg, uptimeMillis),最终将消息压入到消息队列中。
    6. public final void removeMessages(int what):将指定的msg移出消息队列(前提是此msg是处于pending等待的状态);
    7. public final void removeCallbacks(Runnable r):具体使用同6;
    8. public final void removeCallbacksAndMessages(Object token):当token参数传入null的时候会将消息队列中的所有正在pending的msg全部移除;
    9. public final Message obtainMessage():从消息池中得到一个空的msg对象(==推荐使用此方式得到msg对象==)
    10. public void dispatchMessage(Message msg):
      /**
       * 
       * Handle system messages here.
       */
      public void dispatchMessage(Message msg) {
          if (msg.callback != null) {
              handleCallback(msg);
          } else {
              if (mCallback != null) {
                  if (mCallback.handleMessage(msg)) {
                      return;
                  }
              }
              handleMessage(msg);
          }
      }
      
      在此方法中可以看到,handler处理消息的机制中,msg的callback是优先级最高的,即实现的Runnable接口中的run方法;其次是handler自身的CallBack回调,最后才是自身的handleMessage(msg)方法;

    Constructor

    1. public Handler() ;
    2. public Handler(Callback callback) :添加处理msg的回调;
    3. public Handler(Looper looper):添加looper;
    4. public Handler(Looper looper, Callback callback):
    5. public Handler(boolean async):此设置此handler发送的msg是否需要异步处理
    6. public Handler(Callback callback, boolean async) :
    7. public Handler(Looper looper, Callback callback, boolean async) :

    相关文章

      网友评论

          本文标题:Handler消息传递机制解析

          本文链接:https://www.haomeiwen.com/subject/rteinctx.html