handler的原理

来源:互联网 发布:知乎300txt 编辑:程序博客网 时间:2024/05/19 10:13





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