慢慢揭开Handler的真实面目

236 阅读4分钟

一、Handler定义:

Handler是什么:Handler机制允许你在一个线程的MessageQueue中发送和处理Message对象和Runnable对象。 每个Handler实例都与一个单独的线程以及该线程的消息队列相关联。当你创建一个新的Handler 时它会被绑定到一个Looper上。Handler会将消息和Runnable对象传递给该Looper的消息队 列,并在Looper所在的线程上执行它们。

二、Handler相关知识点:

  • Handler的几个关键要素:Handler、Message、MessageQueue、Looper

  1、Handler:负责将Message或者Runnable发送到消息队列中,并且安排他们被处理

  2、Message:消息对象。

暂时无法在YesV2.0文档外展示此内容

  3、MessageQueue:消息队列,用来存消息。既然是队列,正常就遵循队尾插入,队头取出的原则

  4、Looper:消息队列的管理器,负责不断从消息队列中取出消息并分发到相应的Handler中处理

  • Handler的消息类型: 同步消息、异步消息、同步屏障

    • 同步消息:普通消息
    • 异步消息:调用setAsynchronouse(true)设置异步消息
    • 同步屏障:Message消息中的target字段为null,当在消息队列中插入了屏障消息后,在屏障消息之后的普通消息将不会执行,优先执行异步消息。注意异步消息要和同步屏障一起使用才有效果。

三、Handler流程分析:

Handler 流程 及源码分析:

 //构造Handler的时候会取出looper的队列赋值过来
 public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
         mLooper = looper;
         mQueue = looper.mQueue;
         mCallback = callback;
         mAsynchronous = async;
     }
 

 //通过sendMessage方法发送消息,最终都是调用到此处
 public boolean sendMessageAtTime(@NonNull 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;
         }
         //入队操作
         return enqueueMessage(queue, msg, uptimeMillis);
      }
      
  private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
                long uptimeMillis) {
         //将Handler与target绑定
         msg.target = this;
         msg.workSourceUid = ThreadLocalWorkSource.getUid();
         //设置为异步消息
         if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
      }
  boolean enqueueMessage(Message msg, long when) {
          //按理来说这块既然target为空会抛异常,那怎么会出现同步屏障呢?所以同步屏障肯定不是从这来的
          if (msg.target == null) {
             throw new IllegalArgumentException("Message must have a target.");
        }
         synchronized (this) {
            if (msg.isInUse()) {
                  throw new IllegalStateException(msg + " This message is already in use.");
           }
              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.573      
                 //重新设置链头,将这个消息放在链头 
                  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.next
                 prev.next = msg;
              }
              // We can assume mPtr != 0 because mQuitting is false
                if (needWake) {
                  nativeWake(mPtr);
             }
          }
          return true;
   }
     
//一个线程只能由一个Looper
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));
    }
    
     private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
     }
    
  public static void loop() {
   final Looper me = myLooper();
      if (me == null) {
           throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
         if (me.mInLoop) {
             Slog.w(TAG, "Loop again would have the queued messages be executed"                 + " before this one completed.");
        }
         me.mInLoop = true;
        
           ...
           ...
           
        for (;;) {
            //死循环执行loopOnce
            if (!loopOnce(me, ident, thresholdOverride)) {
                  return;
           }
        }
     }
  
 private static boolean loopOnce(final Looper me,final long ident, 
         final int thresholdOverride){    
      
      //  
      Message msg = me.mQueue.next(); // might block
             ...
             ...
          try {
            
            //调用dispatchMessage分发Message  target就是我们绑定的Handler
            msg.target.dispatchMessage(msg);
             ...
        }      
             
             ...
             ...
             
             
         return true;
     }
     
     
     
   public void dispatchMessage(@NonNull Message msg) {
       if (msg.callback != null) {
            handleCallback(msg);
         } else {
            if (mCallback != null) {
                 if (mCallback.handleMessage(msg)) {
                     return;
                 }
              }
              //Handler 实现线程切换,其实依赖的是 Looper,因为在 Handler 初始化的时候就跟 Looper绑
              //定了,而Looper 又是跟线程绑定的,所以,Handler 最后执行 HandleMessage() 方法的时候
              //的线程就是 Looper 所在的线程。

             //当上面条件均不成立,就会走到此处,就是我们平时重写的handleMessage,一般我们传入的就是getMainLooper,所以就切回到主线程了
            handleMessage(msg);
          }
    }
 

四、总结:

Handler 背后还有 Looper、MessageQueue、Message

  • message:消息。
  • MessageQueue:消息队列,负责消息的存储与管理,负责管理由 Handler 发送过来的 Message。读取会自动删除消息,单链表维护,插入和删除上有优势。在其next()方法中会无限循环,不断判断是否有消息,有就返回这条消息并移除。
  • Looper:消息循环器,负责关联线程以及消息的分发,在该线程下从 MessageQueue获取 Message,分发给Handler,Looper创建的时候会创建一个 MessageQueue,调用loop()方法的时候消息循环开始,其中会不断调用messageQueue的next()方法,当有消息就处理,否则阻塞在messageQueue的next()方法中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也就跟着退出。
  • Handler:消息处理器,负责发送并处理消息,面向开发者,提供 API,并隐藏背后实现的细节。

使用 Handler 前,要先创建 Looper 或者使用主线程的 Looper

主线程的 Looper 不允许退出

Runnable 被封装进了 Message,可以说是一个特殊的 Message