Handler源码解析

作者: Lazy1 | 来源:发表于2019-01-14 15:55 被阅读5次
    • 我们一般使用Handler流程是这样,handel分析版本6.0.1:
     Handler     h =new Handler(){
                @Override public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                }
            };
            Message message = new Message();
            message.obj="xxx";
            h.sendMessage(message);
    
    • 那我们就从构造看起
    public Handler() {
          this(null, false);
     }
    
    public Handler(Callback callback, boolean async) {
           if (FIND_POTENTIAL_LEAKS) {
              final Class<? extends Handler> klass = getClass();
               if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
           }
         }
       //这里开始获取looper,由于我们的looper在主线程已经给我初始化了一个,所以如果我们在主线创建handler这个looper就是ManLooer
        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;
        }
    
      public Handler(Looper looper, Callback callback, boolean async) {
            mLooper = looper;
          mQueue = looper.mQueue;
           mCallback = callback;
           mAsynchronous = async;
      }
    

    这里我们可以看到他最终调用到了三个参数的构造方法。

    • 二接下来我们分析发送方法:
     public final boolean sendMessage(Message msg)
       {
           return sendMessageDelayed(msg, 0);
       }
    

    sendmessage最终调用的方法是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);
       }
    
     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
         msg.target = this;
        if (mAsynchronous) {
           msg.setAsynchronous(true);
         }
          return queue.enqueueMessage(msg, uptimeMillis);
       }
    

    最终在enqueueMessage方法中将此条消息添加到消息队列,等待Looper取出分发,我们看看MessageQueue的enqueueMessage方法,注意这里 msg.target = this;就是handler在enqueueMessage中赋值了

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

    这里我们看到将这条消息放进队列

    • 三现在我们消息也有是不是需要取出消息发送了,取出分发消息就是looper干的事情,我们看看

    我前面也说了,Looper的looper方法是分发消息的,那么他是在什么时候被调用的呢,还记得我们为什么在主线程不用手动调用looper吗?那是因为ActivityThread的Man方法中已经调用了

     public static void main(String[] args) {
    
            Looper.prepareMainLooper();
    
          ActivityThread thread = new ActivityThread();
           thread.attach(false);
    
           if (sMainThreadHandler == null) {
               sMainThreadHandler = thread.getHandler();
         }
    
           if (false) {
               Looper.myLooper().setMessageLogging(new
                      LogPrinter(Log.DEBUG, "ActivityThread"));
           }
    
            // End of event ActivityThreadMain.
           Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            Looper.loop();
    
           throw new RuntimeException("Main thread loop unexpectedly exited");
       }
    }
    
    

    看到了吧, 在这创建了looper并且开启了轮训,所以

     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;
                }
    
              // This must be in a local variable, in case a UI event sets the logger
               Printer logging = me.mLogging;
               if (logging != null) {
                   logging.println(">>>>> Dispatching to " + msg.target + " " +
                           msg.callback + ": " + msg.what);
               }
    
              msg.target.dispatchMessage(msg);
    
              if (logging != null) {
                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
             }
    
               // Make sure that during the course of dispatching the
              // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                  Log.wtf(TAG, "Thread identity changed from 0x"
                           + Long.toHexString(ident) + " to 0x"
                           + Long.toHexString(newIdent) + " while dispatching to "
                         + msg.target.getClass().getName() + " "
                          + msg.callback + " what=" + msg.what);
               }
    
            msg.recycleUnchecked();
        }
       }
    

    我们清楚可以看到 msg.target.dispatchMessage(msg);这个方法,之前也说过msg.target值的就是handler所以他就有回调到handleMessage方法了

    public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
               handleCallback(msg);
           } else {
                if (mCallback != null) {
               if (mCallback.handleMessage(msg)) {
                      return;
                 }
            }
               handleMessage(msg);
          }
       }
    

    以上就是Handler的一个正常的分发流程,相信看完了,你也明白了,为什么我们如果在子线程需要手动创建looper,以及他们之前的关系.

    相关文章

      网友评论

        本文标题:Handler源码解析

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