【Android】Handler、Looper、MessageQueue和Message解析

Handler

handler是和線程MessageQueue隊列關聯發送和處理Message和Runnable的對象。html

1.發送Runnable方法以下:android

  • post(Runnable)
  • postAtTime(Runnable, long)
  • postDelayed(Runnable, long)

2.發送Message方法以下:數組

  • sendEmptyMessage(int)
  • sendMessage(Message)
  • sendMessageAtTime(Message, long)
  • sendMessageDelayed(Message, long)

要注意的是handler發送Runnable對象方法其實是調用SendMessage方法。
直接查看源碼,Runnable做爲入參到getPostMessage轉換成Message對象,Runnable賦值給Message的callback,callback何用等會再講。安全

public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

3.dispatchMessageless

Handler的handleMessage是經過dispatchMessage調用的,因此先講它。handler接收Message一共經過三種方式。異步

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
  • 若msg的callBack不爲空,調用Message的Runnable的run方法<span id = "Message_Runnable"></span>
private static void handleCallback(Message message) {
        message.callback.run();
    }
  • 若Handler的mCallback接口回調不爲空
public interface Callback {
        public boolean handleMessage(Message msg);
    }
  • 最後調用handleMessage
/**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }

4.接收Messageasync

  • handleMessage(Message)

因此沒有接收Runnable方法,也就知道爲何要把發送的Runnable轉成Message了。ide

5.注意!!函數

在子線程中建立Handler必需它的mLooper不能爲空。這點應該都比較清楚,Handler的構造函數中對mLooper是否爲空作了判斷,若爲空則拋出一個異常。因此在子線程中建立Handler以前先調用Looper.prepare()建立Looper以及實例化Looper的MessageQueue和Thread。oop

Looper

Looper是用於在Thread中運行消息隊列的類。Thread默認不關聯Looper。
1.prepare

在線程中調用prepare方法運行loop。
sThreadLocal.get()獲取Looper,若爲空則去new Looper()。

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));
    }

2.loop

讓Looper進入循環處理MessageQueue中的Meessage。loop方法很長裏面主要有for(;;)作線程阻塞不斷從queue中拿Message分發給Hanlder去處理。具體在msg.target.dispatchMessage(msg)。msg.target對象就Hanlder。看這

for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            ...省略部分代碼

            final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...省略部分代碼

            msg.recycleUnchecked();
        }

3.quit

Looper調用loop方法進入死循環,那如何讓Looper中止輪詢MessageQueue呢。Looper提供quit和quitSafely兩個方法退出Looper。

  • quit

quit是非安全的,由於在Looer結束以前可能會存在一些Message還存在MessageQueue中不能被分發。*

Using this method may be unsafe because some messages may not be delivered before the looper terminates.  Consider using {@link #quitSafely} instead to ensure that all pending work is completed in an orderly manner.
  • quitSafely

quit不安全,因此咱們使用quitSafely。保證MessageQueue中的Message被及時分發出去。然而延時的Message則不能在quit後分發出去。
Looper的退出都是調用了MessageQueue的quit。

public void quit() {
    mQueue.quit(false);
}
public void quitSafely() {
    mQueue.quit(true);
}

MessageQueue

如今要講的是MessageQueue。開始以前先把Looper調用quit先講了。MessageQueue的quit只要說safe控制的removeAllFutureMessagesLocked和removeAllMessagesLocked。
1.quit

void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }
  • 當Looper調用quit非安全退出執行removeAllMessagesLocked,循環MessageQueue將退出前隊列中Message所有清空。
private void removeAllMessagesLocked() {
        Message p = mMessages;
        while (p != null) {
            Message n = p.next;
            p.recycleUnchecked();
            p = n;
        }
        mMessages = null;
    }
  • 當Looper調用quitSafely執行removeAllFutureMessagesLocked,獲取當前mMessages的when和SystemClock.uptimeMillis()獲取的boot開始到如今的毫秒時間作比較。若Message的時間超過quit的時間則執行非安全退出的quit下的removeAllMessagesLocked。不然將進入循環將MessageQueue要執行的Message分發出去直到MessageQueue清空或者超時(when > now)。
Ps: 因此handler發送Message或者Runnable的延時時間在這裏起了做用,根據傳入的延時時間作列表排序。
private void removeAllFutureMessagesLocked() {
        final long now = SystemClock.uptimeMillis();
        Message p = mMessages;
        if (p != null) {
            if (p.when > now) {
                removeAllMessagesLocked();
            } else {
                Message n;
                for (;;) {
                    n = p.next;
                    if (n == null) {
                        return;
                    }
                    if (n.when > now) {
                        break;
                    }
                    p = n;
                }
                p.next = null;
                do {
                    p = n;
                    n = p.next;
                    p.recycleUnchecked();
                } while (n != null);
            }
        }
    }

2.enqueueMessage

前面Handler講過發送Message,最終都會去執行queue的enqueueMessage方法。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

MessageQueue排列Message並非以數組形式,MessageQueue只持有當前的mMessages。新加入到隊列的Message會根據它的when判斷它在隊列的位置。還能夠看到若Thread已經dead,則拋出非法異常並把發送的Message回收。

boolean enqueueMessage(Message msg, long when) {
        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) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = 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;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

Message

<span id = "Message"></span>
最後就是Message了。Message主要成員參數有:long when、Bundle data、Handler target、Runnable callback、Message next。能夠看到Message沒有前驅只有一個後繼Message。因此MessageQueue只存當前mMessages也能找到下一個Message。
1.Runnable
Message有成員參數Runnable。還記得Handler的Post的是Runnable而後轉換成Message嗎,原來入參的Runnable到這裏來了。看這裏若Message的Runnable不爲空,Handler的dispathMessage但是會走這邊的。至關於Handler是Post方法,最後接收的時候是執行Runnable的run方法。

最後

其實講這麼多就是爲了摸清楚Handler、Looper、MessageQueue以及Message。整個過程下來理清了Handler做爲Message的接收和發送者,將Message插入MessageQueue中。Looper則是做爲一個搬運者不停地從MessageQueue中拿取Mssage而後丟給Handler。那麼Handler做爲Message接收和發送者爲什麼畫蛇添足經過又是Queue又是Looper繞一圈呢?其實其中也有Thread的參與。因爲主題主要是Handler機制,因此Thread放在下次有時間單獨講。Handler就是解決進程間通訊問題以及異步處理事件,建立子線程作異步操做,把但願返回的內容返回到主線程達到不阻塞UI線程的目的。

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();
      }
  }

拿了一張比較好理解的Handler機制運行的圖片來作結束。圖片來源已經在本文最後附上連接
clipboard.png

參考

相關文章
相關標籤/搜索