Handler分析

2019-10-25  本文已影响0人  gaga丶
private Handler mHandler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //主线程更新ui   线程之间的通讯
    }
};
 new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            //子线程发送消息
            Message message=Message.obtain();
            message.obj="Handler Test";
            mHandler.sendMessage(message);
        }
    }).start();

为什么使用Message.obtain()而不是new Message();

查看是否有回收的消息,如果有回收消息就使用回收的消息,不用再去创建Message;

1、sendMessage
mHandler.sendMessage(message); ——> sendMessageDelayed ——>
sendMessageAtTime ——> enqueueMessage(MessageQueue queue, Message msg, long
uptimeMillis)

enqueueMessage:消息队列(链表)按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;
      }

2、Loop消息循环
创建handler的时候创建Looper
mLooper = Looper.myLooper();——》return sThreadLocal.get();——》Thread t = Thread.currentThread();
拿到当前的线程

一个Handler中只有一个Looper,子线程中使用Handler必须先调用Looper.prepare();不然会报错,我们在主线程中并没有调用过 Looper.prepare,为什么不报错?
主线程不用 Looper.prepare
因为我们在应用启动的时候,ActivityThread的入口函数 main()方法中已经帮我们写了这行代码
Looper.prepareMainLooper //准备循环
sThreadLocal.set(new Looper(quitAllowed));

Thread t = Thread.currentThread();
//从线程中获取ThreadLocalMap
ThreadLocalMap map = getMap(t);
 if (map != null)
      map.set(this, value);
 else
      createMap(t, value);

总结:其实就是创建一个Looper,并且保证一个Thread线程中,只有一个Looper对象

      Looper.loop   //循环
      public static void loop() {
            //获取线程的Looper对象
            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;

            for (;;) {
                //死循环不断获取消息队列中的消息
                Message msg = queue.next(); // might block
                if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
              }

               try {
                     //通过Handler去执行essage,这个时候就调用了handlerMessage方法
                     //msg.target是当前handler   再handler。sendMessage()方法中  msg.target=this;
                      msg.target.dispatchMessage(msg);
                      dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
                      } finally {
                            if (traceTag != 0) {
                            Trace.traceEnd(traceTag);
                              }
                        }
                   //回收消息
                    msg.recycleUnchecked();
                  }
        }
上一篇下一篇

猜你喜欢

热点阅读