美文网首页
Handler源码阅读

Handler源码阅读

作者: 坠叶飘香 | 来源:发表于2019-05-17 11:18 被阅读0次

    1. Handler构造方法

    final Looper mLooper;
    final MessageQueue mQueue;
    
    public Handler(Callback callback, boolean async) {
      mLooper = Looper.myLooper();
      if (mLooper == null) {
        throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    

    2. 给Handler发送一个消息

    该Message将会保存在Handler的Looper的MessageQueue的链表结构里
    2.1 sendMessage
    public final boolean sendMessage(Message msg) {
      return sendMessageDelayed(msg, 0);
    }
    
    2.2 sendMessageDelayed
    public final boolean sendMessageDelayed(Message msg, long delayMillis){
      if (delayMillis < 0) {
        delayMillis = 0;
      }
      return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    
    2.3 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;
      }
      return enqueueMessage(queue, msg, uptimeMillis);
    }
    
    2.4 enqueueMessage
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
      msg.target = this;  //Message.target设置为Handler
      if (mAsynchronous) {
        msg.setAsynchronous(true);
      }
      return queue.enqueueMessage(msg, uptimeMillis); //调用MessageQueue 的enqueueMessage方法
    }
    
    2.5 enqueueMessage
    MessageQueue里面安装时间顺序,将msg存放在链表结构里。

    frameworks/base/core/java/android/os/MessageQueue.java

    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.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;
    }
    

    3 执行链表的消息

    3.1 Looper循环处理链表的的Message

    frameworks\base\core\java\android\os\Looper.java

    public static void loop() {
      final Looper me = myLooper();
      if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
      }
      final MessageQueue queue = me.mQueue;
    
      // Make sure the identity of this thread is that of the local process,
      // and keep track of what that identity token actually is.
      Binder.clearCallingIdentity();
      final long ident = Binder.clearCallingIdentity();
    
      for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
          // No message indicates that the message queue is quitting.
          return;
        }
        try {
          msg.target.dispatchMessage(msg);
        } finally {
        }
        msg.recycleUnchecked();
      }
    }
    
    3.2 调用Handler的handleMessage方法

    android\frameworks\base\core\java\android\os\Handler.java

    public void dispatchMessage(Message msg) {
      if (msg.callback != null) {
        handleCallback(msg);
      } else {
        if (mCallback != null) {
          if (mCallback.handleMessage(msg)) {
            return;
          }
        }
        handleMessage(msg); //调用Handler的handleMessage方法
      }
    }
    

    4.Message的重用

    读取:从Message自身的缓存链表重用Message

    frameworks/base/core/java/android/os/Message.java

    public static Message obtain() {
      synchronized (sPoolSync) {
        if (sPool != null) {
          Message m = sPool;
          sPool = m.next;
          m.next = null;
          m.flags = 0; // clear in-use flag
          sPoolSize--;
          return m;
        }
      }
      return new Message();
    }
    
    存入:Message处理完后,放入缓存链表
    void recycleUnchecked() {
      // Mark the message as in use while it remains in the recycled object pool.
      // Clear out all other details.
      flags = FLAG_IN_USE;
      what = 0;
      arg1 = 0;
      arg2 = 0;
      obj = null;
      replyTo = null;
      sendingUid = -1;
      when = 0;
      target = null;
      callback = null;
      data = null;
    
      synchronized (sPoolSync) {
        if (sPoolSize < MAX_POOL_SIZE) { //缓存个数最大值50
          next = sPool;
          sPool = this; //放入表头 
          sPoolSize++;
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:Handler源码阅读

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