一、簡介
二、源碼分析 Looper.class的關(guān)鍵源碼:
//保存Looper對(duì)象,在android中每創(chuàng)建一個(gè)消息隊(duì)列,就有一個(gè)并且是唯一一個(gè)與之對(duì)應(yīng)的Looper對(duì)象 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); //主線程的Looper private static Looper sMainLooper; //消息隊(duì)列 final MessageQueue mQueue; final Thread mThread; //子線程中通過調(diào)用該方法來創(chuàng)建消息隊(duì)列 public static void prepare() { prepare(true); } 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)); } //主線程調(diào)用該方法來創(chuàng)建消息隊(duì)列 public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } //實(shí)例化Looper,創(chuàng)建消息隊(duì)列,獲取當(dāng)前線程 private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } //調(diào)用loop方法開啟消息循環(huán) public static void loop() { //獲取當(dāng)前的Looper對(duì)象,若為null,拋出異常 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //獲取當(dāng)前的消息隊(duì)列,進(jìn)入循環(huán) final MessageQueue queue = me.mQueue; for (;;) { //調(diào)用next()方法從消息隊(duì)列中獲取消息,如果為null,結(jié)束循環(huán);否則,繼續(xù)執(zhí)行(有可能會(huì)阻塞) Message msg = queue.next(); if (msg == null) { return; } ...... try { //調(diào)用handler的dispatchMessage(msg)分發(fā)消息 msg.target.dispatchMessage(msg); } finally { ...... } //回收消息資源 msg.recycleUnchecked(); } } //消息循環(huán)退出 public void quit() { mQueue.quit(false); } public void quitSafely() { mQueue.quit(true); }
消息循環(huán)退出過程 從上面可以看到loop()方法是一個(gè)死循環(huán),只有當(dāng)MessageQueue的next()方法返回null時(shí)才會(huì)結(jié)束循環(huán)。那么MessageQueue的next()方法何時(shí)為null呢? 在Looper類中我們看到了兩個(gè)結(jié)束的方法quit()和quitSalely()。
MessageQueue.class 的關(guān)鍵源碼: MessageQueue中最重要的就是兩個(gè)方法: /* *MessageQueue中enqueueMessage方法的目的有兩個(gè): *1.插入消息到消息隊(duì)列 *2.喚醒Looper中等待的線程(如果是即時(shí)消息并且線程是阻塞狀態(tài)) */ boolean enqueueMessage(Message msg, long when) { //發(fā)送該消息的handler為null,拋出異常 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) { //此消息隊(duì)列已經(jīng)被放棄了 if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); msg.recycle(); return false; } msg.markInUse(); msg.when = when; //消息隊(duì)列的第一個(gè)元素,MessageQueue中的成員變量mMessages指向的就是該鏈表的頭部元素。 Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { //如果此隊(duì)列中頭部元素是null(空的隊(duì)列,一般是第一次),或者此消息不是延時(shí)的消息,則此消息需要被立即處理, //將該消息作為新的頭部,并將此消息的next指向舊的頭部。如果是阻塞狀態(tài)則需要喚醒。 msg.next = p; mMessages = msg; needWake = mBlocked; } else { //如果此消息是延時(shí)的消息,則將其添加到隊(duì)列中, //原理就是鏈表的添加新元素,按照時(shí)間順序來插入的,這樣就得到一條有序的延時(shí)消息鏈表 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; prev.next = msg; } if (needWake) { nativeWake(mPtr); } } return true; } Message next() { //與native方法相關(guān),當(dāng)mPtr為0時(shí)返回null,退出消息循環(huán) final long ptr = mPtr; if (ptr == 0) { return null; } int pendingIdleHandlerCount = -1; //0不進(jìn)入睡眠,-1進(jìn)入睡眠 int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { //處理當(dāng)前線程中待處理的Binder進(jìn)程間通信請(qǐng)求 Binder.flushPendingCommands(); } //native方法,nextPollTimeoutMillis為-1時(shí)進(jìn)入睡眠狀態(tài) //阻塞方法,主要是通過native層的epoll監(jiān)聽文件描述符的寫入事件來實(shí)現(xiàn)的。 //如果nextPollTimeoutMillis=-1,一直阻塞不會(huì)超時(shí)。 //如果nextPollTimeoutMillis=0,不會(huì)阻塞,立即返回。 //如果nextPollTimeoutMillis>0,最長阻塞nextPollTimeoutMillis毫秒(超時(shí)),如果期間有程序喚醒會(huì)立即返回 nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; if (msg != null && msg.target == null) { do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } 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 { //正常取出消息,設(shè)置mBlocked = false代表目前沒有阻塞 mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; msg.markInUse(); return msg; } } else { // No more messages.更新到睡眠狀態(tài) 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); } } //非睡眠狀態(tài)下處理IdleHandler接口 for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; // release the reference to the handler mPendingIdleHandlers[i] = null; boolean keep = false; try { keep = idler.queueIdle(); } catch (Throwable t) { Log.wtf(TAG, "IdleHandler threw exception", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } } } pendingIdleHandlerCount = 0; nextPollTimeoutMillis = 0; } }
Handler.class源碼分析: /* *通過handler類向線程的消息隊(duì)列發(fā)送消息, *每個(gè)Handler對(duì)象中都有一個(gè)Looper對(duì)象和MessageQueue對(duì)象 */ public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } //獲取Looper對(duì)象 mLooper = Looper.myLooper(); if (mLooper == null) {...} //獲取消息隊(duì)列 mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } /* *多種sendMessage方法,最終都調(diào)用了同一個(gè)方法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; } //向消息隊(duì)列中添加消息 return enqueueMessage(queue, msg, uptimeMillis); } /* *1.當(dāng)Message中的callback不為null時(shí),執(zhí)行Message中的callback中的方法。這個(gè)callback時(shí)一個(gè)Runnable接口。 *2.當(dāng)Handler中的Callback接口不為null時(shí),執(zhí)行Callback接口中的方法。 *3.直接執(zhí)行Handler中的handleMessage()方法。 */ public void dispatchMessage(Message msg) { // 消息Callback接口不為null,執(zhí)行Callback接口 if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { //Handler Callback接口不為null,執(zhí)行接口方法 if (mCallback.handleMessage(msg)) { return; } } //處理消息 handleMessage(msg); } }
|
|