標籤:hat empty 操作 targe android源碼 can 消費者模式 get llb
Handler的執行個體化
在安卓開發中,經常會用到Handler將任務提交到指定線程(例如主線程)去執行或者讓其順延強制。Handler的建構函式有多種重載形式,但最終都調用到如下兩種之一:
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;}
可以看到:這兩個建構函式的區別只是Looper的擷取方式不一樣,當未指定Looper時,Handler內部會通過Looper.myLooper()靜態方法,擷取當前線程的Looper。我們往Handler上發送的Message或者Runnable正是由這個Looper(或該Looper的線程)負責處理的。我們可以通過Looper.getMainLooper()擷取主線程的Looper。
發送Message或者Runnable
調用post、postAtTime、postDelayed提交Runnable,調用sendMessage、sendEmptyMessage、sendMessageDelayed、sendEmptyMessageDelayed、sendMessageAtTime、sendEmptyMessageAtTime發送Message,最終都調用到sendMessageAtTime:
1 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 2 MessageQueue queue = mQueue; 3 if (queue == null) { 4 RuntimeException e = new RuntimeException( 5 this + " sendMessageAtTime() called with no mQueue"); 6 Log.w("Looper", e.getMessage(), e); 7 return false; 8 } 9 return enqueueMessage(queue, msg, uptimeMillis);10 }11 12 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {13 msg.target = this;14 if (mAsynchronous) {15 msg.setAsynchronous(true);16 }17 return queue.enqueueMessage(msg, uptimeMillis);18 }
也就是說,提交的Runnable最終會被封裝成Message,此時Message的callback欄位將指向該Runnable。所有提交的Message都將會被插入名為mQueue的有序隊列中,排序的依據便是傳入的uptimeMillis(該值在enqueueMessage操作中會被賦給Message的when欄位)。MessageQueue使用生產者-消費者模式,post*和send*產生的訊息,最終會被Looper消費。(第2行中將mQueue賦給局部變數queue再通過改變訪問mQueue,顯然是出於多線程並發的安全性考慮)
使用postAtFrontOfQueue、sendMessageAtFrontOfQueue可以分別提交Runnable和Message到mQueue的隊首,該Runnable或者Message將在Looper的下次迴圈中處得到處理。
使用removeCallbacks、removeMessages、removeCallbackAndMessages可以移除掉已經提交的Runnable或者Message。
Android源碼學習(1) Handler