歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android-初識Handler,Looper,Message(-) 源碼

Android-初識Handler,Looper,Message(-) 源碼

日期:2017/3/1 10:56:26   编辑:Linux編程

本文只是表面的帶大家浏覽下Handler,Looper,Message的源碼

Android的消息處理有三個核心類:Looper,Handler和Message。其實還有一個Message Queue(消息隊列),

異步處理大師 Handler:

什麼是handler?handler扮演了往MQ上添加消息和處理消息的角色(只處理由自己發出的消息),即通知MQ它要執行一個任務(sendMessage),並在loop到自己的時候執行該任務(handleMessage),整個過程是異步的。handler創建時會關聯一個looper,默認的構造方法將關聯當前線程的looper,不過這也是可以set的。默認的構造方法:

  1. public class handler {
  2. final MessageQueue mQueue; // 關聯的MQ
  3. final Looper mLooper; // 關聯的looper
  4. final Callback mCallback;
  5. // 其他屬性
  6. public Handler() {
  7. if (FIND_POTENTIAL_LEAKS) { // 沒看懂,直接略過,,,
  8. final Class<? extends Handler> klass = getClass();
  9. if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
  10. (klass.getModifiers() & Modifier.STATIC) == 0) {
  11. Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
  12. klass.getCanonicalName());
  13. }
  14. }
  15. // 默認將關聯當前線程的looper
  16. mLooper = Looper.myLooper();
  17. // looper不能為空,即該默認的構造方法只能在looper線程中使用
  1. //UI主線程中默認帶有一個Looper
  2. if (mLooper == null) {
  3. throw new RuntimeException(//不能在沒有Looper的線程上創建Handler,
  4. "Can't create handler inside thread that has not called Looper.prepare()");
  5. }
  6. // 重要!!!直接把關聯looper的MQ作為自己的MQ,因此它的消息將發送到關聯looper的MQ上
  7. mQueue = mLooper.mQueue;
  8. mCallback = null;
  9. }
  10. // 其他方法
  11. }

當然這只是Handler的一個構造方法。Handler本身有四個構造函數,其他其他的三個你可以通過查看源碼來解析,大致雷同。

Handler發送消息

有了handler之後,我們就可以使用 post(Runnabl),sendMessage(Message)這些方法向MQ上發送消息了。光看這些API你可能會覺得handler能發兩種消息,一種是Runnable對象,一種是message對象,這是直觀的理解,但其實post發出的Runnable對象最後都被封裝成message對象了,見源碼:
Post發送的形式

  1. public final boolean post(Runnable r){//使用Post發送消息
  2. return sendMessageDelayed(getPostMessage(r), 0);
  3. }
  1. private final Message getPostMessage(Runnable r) {//把一個Runnable包轉成一個Message
  2. Message m = Message.obtain();
  3. m.callback = r;
  4. return m;
  5. }
  1. public final boolean sendMessageDelayed(Message msg, long delayMillis){
  2. if (delayMillis < 0) {
  3. delayMillis = 0;
  4. }
  5. return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  6. }
  1. <pre class="java" name="code"><pre class="java" name="code">public boolean sendMessageAtTime(Message msg, long uptimeMillis){
  2. boolean sent = false;
  3. MessageQueue queue = mQueue;
  4. if (queue != null) {
  1. /*該handler對象,這確保了looper執行到該message時能找到處理它的handler,直白點就是ABC三個Handler發送消息,最終執行的時候Message消息
  1. 也是由他們本身來執行,而不會發生A接受到B發送的Message之類的情況*/
  2. msg.target = this;//
  1. sent = queue.enqueueMessage(msg, uptimeMillis);//壓入消息隊列
  2. }else {
  3. RuntimeException e = new RuntimeException(
  4. this + " sendMessageAtTime() called with no mQueue");
  5. Log.w("Looper", e.getMessage(), e);
  6. }
  7. return sent;

sendMessage(Message)形式

  1. public final boolean sendMessage(Message msg){
  2. return sendMessageDelayed(msg, 0);
  3. }
  1. public final boolean sendMessageDelayed(Message msg, long delayMillis){
  2. if (delayMillis < 0) {
  3. delayMillis = 0;
  4. }
  5. return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  6. }

從源碼中我們中我們可以很清晰的看到無論是用psot(Runnable)還是使用sendMessage(Message)方法,最後他們都會調用到同一個方法壓入都一個隊列中去。

Copyright © Linux教程網 All Rights Reserved