handler的原理

来源:互联网 发布:知乎300txt 编辑:程序博客网 时间:2024/06/10 00:56





1. Handler
1. new Handler()
 
public Handler() {
//1.
       this(null, false);
   }
//2. 
public Handler(Callback callback, boolean async) {
      
...
//获取轮询器
//3. 看4步
      
//9.
mLooper = Looper.myLooper();
       if (mLooper == null) {
           throw new RuntimeException(
               "Can't create handler inside thread that has not called Looper.prepare()");
       }
//10. 获取消息队列MessageQueue
       mQueue = mLooper.mQueue;
       mCallback = callback;
       mAsynchronous = async;
   }
           //4.Looper.myLooper();
  return sThreadLocal.get();
//5. 赋值Looper(主线程)
ActivityThread
          // 6.  main()
Looper.prepareMainLooper();
          //7. Looper.prepareMainLooper();
prepare(false);
       synchronized (Looper.class) {
           if (sMainLooper != null) {
               throw new IllegalStateException("The main Looper has already been prepared.");
           }
           sMainLooper = myLooper();
       }
          //8.  prepare(false);
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));
    }
总结:获取Looper器对象和消息队列

2. handler.sendMessage();
发送消息:看下面标记

2. Message


1. new Message 


public Message() {
    }






2. Message.obtain()  
       
public static Message obtain() {
       synchronized (sPoolSync) {
           if (sPool != null) {// sPool  Message
               Message m = sPool;
               sPool = m.next;
               m.next = null;
               sPoolSize--;
               return m;
           }
       }
       return new Message();
    }
方法重载很多,每个方法的本质都会走上面代码


3. mHandler.obtainMessage()

Message.obtain(this);  //把handler做绑定


3. Looper
4. MessageQueue




#####ThreadLocal
1. 线程的本地变量,每个线程都可以往tl里set值 ,取的时候根据线程的标记取出对应每个线程set的值




#######发送消息


1.  Message类中的 sendToTarget

public void sendToTarget() {
       target.sendMessage(this);(看2)
   }




2. mHandler.sendMessage(msg);

public final boolean sendMessage(Message msg)
   {
//1.
       return sendMessageDelayed(msg, 0);
   }
//2. sendMessageDelayed(msg, 0);
public final boolean sendMessageDelayed(Message msg, long delayMillis)
   {
       if (delayMillis < 0) {
           delayMillis = 0;
       }
//3.
       return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
   }
//4.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;
       }
//5.  把handler绑定到message并且把消息放到消息队列并且按时间排序
       return enqueueMessage(queue, msg, uptimeMillis);
   }
//6.enqueueMessage(queue, msg, uptimeMillis)


private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//把Handler绑定到Message的target属性
       msg.target = this;//this Handler对象
       if (mAsynchronous) {
           msg.setAsynchronous(true);
       }
//7. 把消息放到消息队列并且按时间排序
       return queue.enqueueMessage(msg, uptimeMillis);
   }
//8. MessageQueue的queue.enqueueMessage
 boolean enqueueMessage(Message msg, long when) {
       ...

       synchronized (this) {
           ...
           msg.when = when;//message的发送时间
           Message p = mMessages;//mMessages MessagQueue的属性Message类型
           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;
                   }
                   。。。唤醒逻辑
               }
               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;
    }


#######取并处理消息
1. Looper.loop();//轮询
2. loop方法


public static void loop() {
       final Looper me = myLooper();
       if (me == null) {
           throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
       }
//从轮询器中获取消息队列和Handler 的queue 是同一个消息队列
       final MessageQueue queue = me.mQueue;

    ...

       for (;;) {
//MessageQueue的next方法
//1. 取消息看2
           Message msg = queue.next(); // might block
          //处理消息
//3. 处理消息看4
           msg.target.dispatchMessage(msg);

           ...
//回收消息 kan 6
           msg.recycle();
       }
    }


// 2. MessageQueue的next方法
Message next() {
       int pendingIdleHandlerCount = -1; // -1 only during first iteration
       int nextPollTimeoutMillis = 0;
       for (;;) {
           if (nextPollTimeoutMillis != 0) {
               Binder.flushPendingCommands();
           }

           // We can assume mPtr != 0 because the loop is obviously still running.
           // The looper will not call this method after the loop quits.
           nativePollOnce(mPtr, 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) {
                   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 (false) Log.v("MessageQueue", "Returning message: " + msg);
                       msg.markInUse();
                       return msg;
                   }
               } else {
                   // No more messages.
                   nextPollTimeoutMillis = -1;
               }

               // Process the quit message now that all pending messages have been handled.
               if (mQuitting) {
                   dispose();
                   return null;
               }

               // If first time idle, then get the number of idlers to run.
               // Idle handles only run if the queue is empty or if the first message
               // in the queue (possibly a barrier) is due to be handled in the future.
               if (pendingIdleHandlerCount < 0
                       && (mMessages == null || now < mMessages.when)) {
                   pendingIdleHandlerCount = mIdleHandlers.size();
               }
               if (pendingIdleHandlerCount <= 0) {
                   // No idle handlers to run.  Loop and wait some more.
                   mBlocked = true;
                   continue;
               }

               if (mPendingIdleHandlers == null) {
                   mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
               }
               mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
           }

           // Run the idle handlers.
           // We only ever reach this code block during the first iteration.
           for (int i = 0; i < pendingIdleHandlerCount; i++) {
               final IdleHandler idler = mPendingIdleHandlers[i];
               mPendingIdleHandlers[i] = null; // release the reference to the handler

               boolean keep = false;
               try {
                   keep = idler.queueIdle();
               } catch (Throwable t) {
                   Log.wtf("MessageQueue", "IdleHandler threw exception", t);
               }

               if (!keep) {
                   synchronized (this) {
                       mIdleHandlers.remove(idler);
                   }
               }
           }

           // Reset the idle handler count to 0 so we do not run them again.
           pendingIdleHandlerCount = 0;

           // While calling an idle handler, a new message could have been delivered
           // so go back and look again for a pending message without waiting.
           nextPollTimeoutMillis = 0;
       }
   }


//4. msg.target.dispatchMessage(msg);
msg.target  handler
dispatchMessage 是handler的方法


public void dispatchMessage(Message msg) {
       if (msg.callback != null) {
//回调 看5
           handleCallback(msg);
       } else {
           if (mCallback != null) {
               if (mCallback.handleMessage(msg)) {
                   return;
               }
           }
//处理消息 主线程调用
           handleMessage(msg);
       }
   }
//5. 回调
handleCallback(msg);


private static void handleCallback(Message message) {
       message.callback.run();//主线程中调用
   }


//6. 回收消息(把消息放到消息池中) msg.recycle();
public void recycle() {
//7.
       clearForRecycle();

       synchronized (sPoolSync) {
           if (sPoolSize < MAX_POOL_SIZE) {
               next = sPool;
               sPool = this;
               sPoolSize++;
           }
       }
   }
      //7. clearForRecycle();
/*package*/ void clearForRecycle() {
       flags = 0;
       what = 0;
       arg1 = 0;
       arg2 = 0;
       obj = null;
       replyTo = null;
       when = 0;
       target = null;
       callback = null;
       data = null;
   }
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 学车证明丢失怎么办? 哈尔滨空挂户口怎么办 厦大学生怎么办厦门居住证 厦门网上办理居住证怎么办 宝宝风热咳嗽怎么办 小孩感冒后鼻炎怎么办 小孩感冒引起鼻炎怎么办 婴幼儿喉咙有痰怎么办 驾校的居住证明怎么办 去韩国留学护照怎么办 去韩国签证怎么办d4 出国留学拒签怎么办 高中毕业考不上大学怎么办 深圳怎么办客运营运证 深圳龙岗怎么办居住证 想去日本怎么办签证 孩子没有出生证怎么办通行证 去日本旅游怎么办签证 去美国旅游签证怎么办 我想去泰国怎么办签证 怎么办去泰国的签证 去韩国工作怎么办签证 去越南打工怎么办签证 越南到中国签证怎么办 去越南工作签证怎么办 马来西亚留学签证过期后怎么办 日本留学存款不够怎么办 没有工作单位怎么办签证 深户日本签证怎么办 土耳其跟团签证怎么办 公司取消交通车职工怎么办 出国健康证丢失怎么办 大三阳怎么办健康证 办不了健康证怎么办 办健康证不合格怎么办 美团健康证怎么办 便检取样很多怎么办 拉不出大便怎么办马上解决方法 无业人员怎么办健康证 健康证没身份证怎么办 身份证过期了怎么办护照