Handler:Handler容許你發送而且處理和線程消息隊列相關的消息(Message)和可運行對象。每一個Handler實例都有一個單獨的相關線程和這個線程的消息隊列。當你建立一個新的Handler時候,它將和建立者所在線程以及此線程的消息隊列綁定。從這一刻起,它將傳遞消息和可運行對象到消息隊列,並在消息和可運行對象被傳出消息隊列時執行它們。 java
Handler主要有兩種用途:(1)把要被執行的消息和可運行對象添加到將要執行的任務清單裏。(2)把要在另一條線程上執行的動做列入本身的隊列。 ide
安排消息到任務清單,可使用如下幾種方法:post,postAtTime(Runnable,long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime以及sendMessageDelayed方法。post版本的方法容許你安排Runnable對象到任務清單,這些Runnable對象將在消息隊列接收到後調用它們。sendMessage版本的方法容許你安排一個Message對象到任務清單,這個Message對象包含一個將被Hanlder的handleMessage方法處理的數據包(須要在你的子類中實現handleMessage方法)。 oop
你在posting或者sending時,既能夠容許消息循環在準備完成後當即處理任務,也能夠在執行任務以前指定一個延遲時間。上述post和send系列的最後兩個方法能夠設置超時、空轉和定時行爲。 post
當你的應用程序建立一個進程的時候,這個進程的主線程就專門運行一個負責管理頂級程序對象(activities,broadcast receivers等等)和全部由這些對象建立的窗口的消息循環。你能夠建立本身的線程,而且經過一個Handler和應用的主線程溝通。這樣作跟以前調用post或者sendMessage同樣,只不過是在你的子線程中調用的。給定的Runnable對象或者Message將被添加到Hanlder的消息隊列,而且在適當的時候處理它們。 ui
Hanlder默認的構造方法,將這個Handler跟當前線程中的隊列關聯了起來: this
public Handler() { 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 = null; }
Handler必需要有一個消息隊列,否則它無法接受消息。在線程初始化Handler以前,必須調用Looper.prepare(),詳細內容請參考《Android之Looper》。 spa
初始化Handler時,還能夠指定Looper和Callback,前者可使消息循環在Looper相關的線程中運行,後者可使你避免重寫Handler。 .net
Handler的obtainMessage系列方法都是從全局的消息池中拿Message,若是池中沒有,就new一個返回。 線程
post系列方法,都是封裝的對應的send系列方法(將Runnable對象(msg.callback)和一個Object對象(即msg.object,若是有的話)經過getPostMessage方法拿到一個Message,而後send)。 code
private final Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; }
send系列方法,包裝的都是sendMessageAtTime方法(sendMessageAtFrontOfQueue方法也是它的一個變種)。在sendMessageAtTime方法中,第一個參數是將被傳遞的Message對象,第二個是傳遞時的時間(能夠猜測delayed系列方法都是當前時間加上延遲時間,事實證實這種猜測是正確的)。
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
在這個方法中,將Message排入消息隊列(隊列中按照uptimeMillis排序,而sendMessageAtFrontOfQueue方法中將它設爲0,因此sendMessageAtFrontOfQueue方法傳遞的Message將在Looper的loop方法循環的下一次循環中當即執行)。enqueueMessage方法的排序部分以下:
synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } }
將Message排入消息隊列後的事情,是由Looper來完成的,詳見《Android之Looper》中的loop方法。在Looper的loop方法中,調用了msg.target(即Handler,見sendMessageAtTime方法)的dispatchMessage方法。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
第一個判斷,msg.callback即爲post系列方法傳遞到的Runnable對象。
private final void handleCallback(Message message) { message.callback.run(); }
第二個mCallback.handleMessage方法,可讓你避免在本身的Handler子類中重寫handleMessage方法。
還有remove系列方法,就是根據條件從消息隊列中移除相關的Message。