Android應用程序是經過消息來驅動的,每一個應用程序都有一個Main looper在ActivityThread中建立。咱們這一節中就主要來分析下Looper和Handler的實現機制,首先來簡單介紹一下它們的關係: java
▪Thread、Looper、MessageQueue、Handler的關係
–Thread線程是整個Looper循環執行的場所
–Looper消息泵,不斷的從MessageQueue中讀取消息並執行,Looper就是一個無限循環,Looper中包含MessageQueue
–MessageQueue消息隊列,負責存放消息
–Looper分發消息給Handler執行;Handler同時能夠向MessageQueue添加消息
咱們經過下面一個簡單的程序來看一下如何使用Looper和Handler:
- class LooperThread extends Thread {
- public Handler mHandler;
- public void run() {
- Looper.prepare();
- mHandler = new Handler() {
- public void handleMessage(Message msg) {
- // process incoming messages here
- }
- };
- Looper.loop();
- }
- }
首先在一個Thread中須要先調用Looper.prepare方法去作好初始化工做,其實就是實例化一個MessageQueue。而後調用Looper.loop就能夠開始循環了。那咱們首先先看一下prepare方法:
- 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));
- }
-
- private Looper(boolean quitAllowed) {
- mQueue = new MessageQueue(quitAllowed);
- mThread = Thread.currentThread();
- }
能夠看到在prepare方法中主要是構造一個Looper對象並存放在sThreadLocal中,sThreadLocal是線程本地存儲的變量,每一個線程有這麼一塊區域來存儲線程的數據,這些數據不會被進程中其它線程所修改。在Looper的構造函數中實例化一個MessageQueue對象:
- MessageQueue(boolean quitAllowed) {
- mQuitAllowed = quitAllowed;
- mPtr = nativeInit();
- }
-
- static jint android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
- NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
- if (!nativeMessageQueue) {
- jniThrowRuntimeException(env, "Unable to allocate native queue");
- return 0;
- }
-
- nativeMessageQueue->incStrong(env);
- return reinterpret_cast<jint>(nativeMessageQueue);
- }
在MessageQueue的構造函數中經過JNI調用到android_os_MessageQueue_nativeInit方法,在這個方法裏面,構造一個NativeMessageQueue對象,並在Java層的MessageQueue成員變量mPtrl保存NativeMessageQueue對象的內存地址,以便後面Java層調用NativeMessageQueue的其它方法。咱們再來看一下NativeMessageQueue的構造函數:
- NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
- mLooper = Looper::getForThread();
- if (mLooper == NULL) {
- mLooper = new Looper(false);
- Looper::setForThread(mLooper);
- }
- }
在Native層的MessageQueue中,也經過TLS技術在線程中保存是否建立了底層Looper,若是有建立就能夠經過getForThread返回;若是沒有,getForThread將返回NULL。固然這裏確定會返回NULL,這裏就將構造一個Looper對象並設置到這個線程的TLS中。咱們來看Looper的構造函數:
- Looper::Looper(bool allowNonCallbacks) :
- mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
- mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
- int wakeFds[2];
- int result = pipe(wakeFds);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
-
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
-
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
-
- result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
-
- mIdling = false;
-
- // Allocate the epoll instance and register the wake pipe.
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
-
- struct epoll_event eventItem;
- memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
- eventItem.events = EPOLLIN;
- eventItem.data.fd = mWakeReadPipeFd;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);
- }
Looper的構造函數比較簡單,首先構造一個pipe,一端用於讀,另外一端用於寫。而後使用epoll將它mWakeReadPipeFd添加到mEpollFd中。後面咱們就能夠經過在mWakeWritePipeFd端寫數據,讓epoll_wait跳出等待。當這裏Looper.prepare函數就介紹完了,咱們先來看一下上面說到的幾個類的關係圖:
而後咱們再來分析Looper.loop方法:
- public static void loop() {
- final Looper me = myLooper();
- final MessageQueue queue = me.mQueue;
- Binder.clearCallingIdentity();
- final long ident = Binder.clearCallingIdentity();
- for (;;) {
- Message msg = queue.next(); // might block
- if (msg == null) {
- return;
- }
- msg.target.dispatchMessage(msg);
- final long newIdent = Binder.clearCallingIdentity();
- msg.recycle();
- }
- }
首先myLooper返回ThreadLocal存儲的前面構造的Looper對象。而後調用Looper中的MessageQueue的next方法,next方法返回下一個消息(若是有,若是沒有就一直等待),固然通常狀況下不會返回空消息。並調用msg.target的dispatchMessage方法,這裏的target其實就是Handler,咱們後面再來分析。先來看一下MessageQueue的next方法:
- Message next() {
- int pendingIdleHandlerCount = -1; // -1 only during first iteration
- int nextPollTimeoutMillis = 0;
- for (;;) {
- if (nextPollTimeoutMillis != 0) {
- Binder.flushPendingCommands();
- }
- nativePollOnce(mPtr, 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) {
- nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
- } else {
- mBlocked = false;
- if (prevMsg != null) {
- prevMsg.next = msg.next;
- } else {
- mMessages = msg.next;
- }
- msg.next = null;
- msg.markInUse();
- return msg;
- }
- } else {
- nextPollTimeoutMillis = -1;
- }
- if (mQuitting) {
- dispose();
- return null;
- }
-
- 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);
- }
-
- 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);
- }
- }
- }
- pendingIdleHandlerCount = 0;
- nextPollTimeoutMillis = 0;
- }
- }
next函數雖然比較長,但它的邏輯仍是比較簡單的,主要能夠分爲下面三個步驟:
▪調用nativePollOnce去完成等待。初始值nextPollTimeoutMillis爲0,epoll_wait會立刻返回,當nextPollTimeoutMillis爲-1,epoll_wait會一直等待
▪當nativePollOnce返回後,獲取mMessages中消息。若是mMessages沒有消息,就設置nextPollTimeoutMillis爲-1,表示下一次epoll_wait時一直等待。若是mMessages中有消息,而且當前系統時間不小於messge待處理的時間,就返回這個消息
▪若是沒有消息處理,而且當前有IdleHandlers,就調用IdleHandlers的queueIdle方法,並修改nextPollTimeoutMillis爲0。IdleHandlers用於在MessageQueue中沒有消息時作回調使用。
在上面的三個步驟中,最重要的固然是nativePollOnce,咱們來簡單分析一下:
- void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
- mInCallback = true;
- mLooper->pollOnce(timeoutMillis);
- mInCallback = false;
- if (mExceptionObj) {
- env->Throw(mExceptionObj);
- env->DeleteLocalRef(mExceptionObj);
- mExceptionObj = NULL;
- }
- }
-
- int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
- int result = 0;
- for (;;) {
-
-
- if (result != 0) {
- return result;
- }
-
- result = pollInner(timeoutMillis);
- }
- }
-
- int Looper::pollInner(int timeoutMillis) {
- int result = ALOOPER_POLL_WAKE;
- mResponses.clear();
- mResponseIndex = 0;
-
- // We are about to idle.
- mIdling = true;
-
- struct epoll_event eventItems[EPOLL_MAX_EVENTS];
- int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
-
- // No longer idling.
- mIdling = false;
-
- // Acquire lock.
- mLock.lock();
-
- if (eventCount < 0) {
- if (errno == EINTR) {
- goto Done;
- }
- ALOGW("Poll failed with an unexpected error, errno=%d", errno);
- result = ALOOPER_POLL_ERROR;
- goto Done;
- }
-
- // Check for poll timeout.
- if (eventCount == 0) {
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - timeout", this);
- #endif
- result = ALOOPER_POLL_TIMEOUT;
- goto Done;
- }
-
- for (int i = 0; i < eventCount; i++) {
- int fd = eventItems[i].data.fd;
- uint32_t epollEvents = eventItems[i].events;
- if (fd == mWakeReadPipeFd) {
- if (epollEvents & EPOLLIN) {
- awoken();
- } else {
- }
- } else {
-
- }
- }
- Done: ;
-
- mNextMessageUptime = LLONG_MAX;
- mLock.unlock();
- return result;
- }
由於Native層Looper須要支持底層本身的消息處理機制,因此pollOnce的代碼中添加處理底層Message的代碼,咱們拋開這部分的代碼,其實pollOnce就是調用epoll_wait去等待時間發生。當timeoutMillis爲0時,它會當即返回;當timeoutMillis爲-1時,它會一直等待,知道咱們調用Looper::wake方法向mWakeWritePipeFd寫入數據。咱們簡要來看一下上面介紹prepare和loop的流程:
咱們再來分析下Handler和Message的關係,並介紹如何向MessageQueue中添加消息,以便epoll_wait可以返回。首先來看Handler的構造函數,Handler有不少構造函數,咱們能夠把Handler綁定到一個Looper上,也能夠不帶Looper參數,它會默認的綁定到咱們的MainThread中:
- public Handler(Callback callback) {
- this(callback, false);
- }
-
- public Handler(Looper looper) {
- this(looper, null, false);
- }
-
- public Handler(Callback callback, boolean async) {
- 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;
- }
上面列舉了兩種Handler的構造方法,它主要從當前Looper中獲得MessageQueue對象,並保存在mQueue中,後面咱們就能夠調用mQueue的方法來添加消息了。來看一下Handler和Message的類圖:
來看一下一個簡單的sendMessage方法,固然Message對象能夠經過Message的靜態方法obtain得到:
- public final boolean sendMessage(Message msg)
- {
- return sendMessageDelayed(msg, 0);
- }
-
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- {
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
-
- public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
- MessageQueue queue = mQueue;
- 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);
- }
這裏通過一系列的方法,最終調用到MessageQueue的enqueueMessage函數:
- boolean enqueueMessage(Message msg, long when) {
- if (msg.target == null) {
- throw new AndroidRuntimeException("Message must have a target.");
- }
- synchronized (this) {
- msg.when = when;
- Message p = mMessages;
- boolean needWake;
- if (p == null || when == 0 || when < p.when) {
- msg.next = p;
- mMessages = msg;
- needWake = mBlocked;
- } else {
- 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;
- }
enqueueMessage檢查mMessages中是否有消息,若是沒有,就把它當前頭添加到mMessages中,並更新needWake爲mBlocked,mBlocked會在mMessages爲空而且沒有IdleHandlers時置爲true,這時timeoutMillis爲-1,epoll_wait會無限等待,因此咱們須要調用natvieWake喚醒它;若是在mMessages有消息,咱們通常狀況下不須要調用nativeWake來喚醒,除非咱們當前頭部是barrier消息(target爲NULL)而且待send的消息是第一個異步的,這裏就將調用nativeWake來喚醒它。這裏注意的是異步消息不會被barrier消息打斷,而且異步消息能夠在它以前的同步消息以前執行。再來看一下nativeWake函數的實現:
- static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jint ptr) {
- NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
- return nativeMessageQueue->wake();
- }
-
- void Looper::wake() {
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1);
- } while (nWrite == -1 && errno == EINTR);
-
- if (nWrite != 1) {
- if (errno != EAGAIN) {
- ALOGW("Could not write wake signal, errno=%d", errno);
- }
- }
- }
這裏其實就是向pipe的寫端寫入一個"W"字符,這樣epoll_wait就能夠跳出等待了。咱們先來看一下上面介紹的sendMessage的流程:
當Message的next方法返回一個消息後,後面就將調用Handler的dispatchMessage去處理它:
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }
當咱們post一個Runnable時,Message的callback就爲這個Runnable,若是Runnable不爲空,直接調用callback.run方法。若是msg.callback爲空,但mCallback不爲空,則調用mCallback的handleMessage方法。最後二者都沒有的狀況下才調用Handler的handleMessage方法,因此咱們在程序中通常重載handleMessage來處理消息便可。下面是dispatchMessage的流程圖:
咱們來看下面這段代碼:
- class LooperThread extends Thread {
- public Looper myLooper = null;
- public void run() {
- Looper.prepare();
- myLooper = Looper.myLooper();
- Looper.loop();
- }
- }
-
- {
- LooperThread myLooperThread = new LooperThread();
- myLooperThread.start();
- Looper mLooper = myLooperThread.myLooper;
- Handler mHandler = new Handler(mLooper);
- mHandler.sendEmptyMessage(0);
- }
這在咱們程序中會常常用到,先在一個Thread中準備好Looper,而後使用這個Looper綁定到另一個Handler上面。但上面的程序有點bug,當myLooperThread還沒執行到myLooper = Looper.myLooper()這一行時,主線程接着運行並調用Handler的構造函數,由於此時MessageQueue還沒準備好,因此這裏會拋出一個異常。爲了處理這種問題,Android提供了HandlerThread這個類來完美解決這個問題:
- public HandlerThread(String name, int priority) {
- super(name);
- mPriority = priority;
- }
-
- public void run() {
- mTid = Process.myTid();
- Looper.prepare();
- synchronized (this) {
- mLooper = Looper.myLooper();
- notifyAll();
- }
- Process.setThreadPriority(mPriority);
- onLooperPrepared();
- Looper.loop();
- mTid = -1;
- }
-
- public Looper getLooper() {
- if (!isAlive()) {
- return null;
- }
-
- // If the thread has been started, wait until the looper has been created.
- synchronized (this) {
- while (isAlive() && mLooper == null) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
- return mLooper;
- }
經過wait和notifyAll機制完美解決了以上的問題。看來咱們在程序中仍是要多使用HandlerThread。下面對上面的介紹作一個簡單的總結:
▪Handler的處理過程運行在建立Handler的線程裏 ▪一個Looper對應一個MessageQueue ▪一個線程對應一個Looper ▪一個Looper能夠對應多個Handler ▪當MessageQueue中沒有消息時,IdleHandlers會被回調 ▪MessageQueue中的消息原本是有序的處理,但能夠經過barrier消息將其中斷(打亂)