android handler機制源碼解析【非同步回調】

來源:互聯網
上載者:User

標籤:

流程總結

  1. Looper.prepare():本線程中儲存一個Looper執行個體,然後該執行個體中儲存一個MessageQueue對象;因為Looper.prepare()在一個線程中只能調用一次,所以MessageQueue在一個線程中只會存在一個。
  2. Looper.loop():輪詢MessageQueue,回調msg.target.dispatchMessage(msg)方法。
  3. Handler構造方法:得到當前線程中儲存的Looper執行個體,進而與Looper執行個體中的MessageQueue想關聯。
  4. Handler的sendMessage():會給msg的target賦值為handler自身,然後加入MessageQueue中。
  5. 重寫handleMessage():是msg.target.dispatchMessage(msg)最終調用的方法。

Tip:在Activity的啟動代碼中,已經在當前UI線程調用了Looper.prepare()和Looper.loop()方法。建立handler就不用顯示的調用Looper.prepare()和Looper.loop()

觀察者模式

Looper

建立一個MessageQueue,輪詢MessageQueue

  • 構造方法
    • private Looper(boolean quitAllowed) {          mQueue = new MessageQueue(quitAllowed);          mRun = true;          mThread = Thread.currentThread();  }

    • 建立messageQueue
  • prepare()
    • public static final void prepare() {          if (sThreadLocal.get() != null) {              throw new RuntimeException("Only one Looper may be created per thread");          }          sThreadLocal.set(new Looper(true));  }  

    • 不能被調用2次,有且只有一個
  • loop()
    • looper方法必須在prepare方法之後運行
    • 輪詢,無 -> 阻塞,有 -> msg.target.dispatchMessage(msg);
  • 作用
    • 綁定當前線程,有且只有一個looper執行個體和MessageQueue,輪詢並通知
handler

訊息建立者,非同步分發

public Handler() {          this(null, false);  }  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());              }          }            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;      }  


  • mLooper = Looper.myLooper();  擷取looper
  • mQueue = mLooper.mQueue;擷取messagequeue

public final boolean sendMessage(Message msg)   {       return sendMessageDelayed(msg, 0);   } 

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

  • msg.target = this;  => msg.target.dispatchMessage(msg); handler發出的訊息,最終會儲存到訊息佇列中去
MessagedispathMessage

public void dispatchMessage(Message msg) {          if (msg.callback != null) {              handleCallback(msg);          } else {              if (mCallback != null) {                  if (mCallback.handleMessage(msg)) {                      return;                  }              }              handleMessage(msg);          }      }  

因為訊息的最終回調是由我們控制的,我們在建立handler的時候都是複寫handleMessage方法,然後根據msg.what進行訊息處理

private Handler mHandler = new Handler()      {          public void handleMessage(android.os.Message msg)          {              switch (msg.what)              {              case value:                                    break;                default:                  break;              }          };      };  


  • public int what:變數,用於定義此Message屬於何種操作
  • public Object obj:變數,用於定義此Message傳遞的資訊資料,通過它傳遞資訊
  • public int arg1:變數,傳遞一些整型資料時使用
  • public int arg2:變數,傳遞一些整型資料時使用
  • public Handler getTarget():普通方法,取得操作此訊息的Handler對象。

完成調度資訊
  •  {@link #post}, {@link #postAtTime(Runnable, long)},
  •  {@link #postDelayed}, {@link #sendEmptyMessage},
  •  {@link #sendMessage}, {@link #sendMessageAtTime}, and
  •  {@link #sendMessageDelayed} methods.  The <em>post</em> versions allow
Handler post

mHandler.post(new Runnable()          {              @Override              public void run()              {                  Log.e("TAG", Thread.currentThread().getName());                  mTxt.setText("yoxi");              }          });  

Runnable並沒有建立什麼線程,而是發送了一條訊息
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;    }  
在getPostMessage中,得到了一個Message對象,然後將我們建立的Runable對象作為callback屬性,賦值給了此message.

註:

  • 產生一個Message對象,可以new  ,也可以使用Message.obtain()
  • Message內部維護了一個Message池用於Message的複用,使用Message.obtain()方法避免使用new 重新分配記憶體。
  • 如果你的message只需要攜帶簡單的int資訊,請優先使用Message.arg1和Message.arg2來傳遞資訊,這比用Bundle更省記憶體
  • 擅用message.what來標識資訊,以便用不同方式處理message

如果不為null,則執行callback回調,也就是我們的Runnable對象。


問題

1,使用Handler 是非同步,它會建立新的線程嗎? 不會
2,Handler 是在主線程內嗎? 一般都會在主線程內,但也可以在子線程中建立Handler
3,Handler 的 post 和 sendMessage 方法,使用的是一個隊列不安是兩個? 一個
4,子線程中建立一個 handler, 然後sendMessage 會怎麼樣? 會崩潰
5,子線程建立 handler ,構造的時候舒心入主線程的 Looper ? yes




android handler機制源碼解析【非同步回調】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.