Handler
- Handler構造方法
- 建立訊息obtainMessage
傳送訊息sendMessage
移除訊息removeMessage
處理訊息dispatchMessage
Handler一些特點
Handler例項
Handler總是依附於建立時所在的執行緒,比如我們的Handler是在主執行緒中建立的,而在子執行緒中又無法直接對UI進行操作,於是我們就通過一系列的傳送訊息、入隊、出隊等環節,最後呼叫到了Handler的handleMessage()方法中,這時的handleMessage()方法已經是在主執行緒中執行的,因而我們當然可以在這裡進行UI操作了。整個非同步訊息處理流程的示意圖如下圖所示:
Handler
這便是我們平時直接使用的主角。繼承Handler
重寫其handleMessage()
方法來處理訊息,在需要的時候呼叫sendMessage()
來發訊息,剩下的就不用管了。現在來看看“我們不用管”的這部分都幹了點啥。
構造方法
所有的構造方法最終會會呼叫兩個實現,如果制定了Looper,則會呼叫三個引數的過載,否則會呼叫兩個引數的過載。而後者則會呼叫Lopper.myLooper()
來獲取looper。兩個構造方法除了給mLooper
賦值外,還給mQueue
賦值為mLooper.mQueue
;給mCallback
賦值為指定的callback或null;給mAsynchronous
賦值為指定的boolean或false。 在兩個引數的構造方法中,給上述四個成員賦值前有段if(FIND_POTENTIAL_LEAKS){}
包裹的程式碼段,該變數定義為private static final boolean FIND_POTENTIAL_LEAKS = false;
因此推斷這部分是開發時除錯用的,此處不做理會。
建立訊息obtainMessage()
根據原始碼可以看出,所有該方法的過載都呼叫了Message.obtain()
對應的過載,可以看Message.obtain()的來龍去脈來了解,此處不再贅述。需要注意的是,每個過載都傳入了this
引數並賦值給了message的target
。這裡先記著就行,後面會介紹如何通過target
呼叫dispatchMessage()
處理訊息。
傳送訊息sendMessage()
所有的sendEmptyMessage()
過載與sendMessageXXX()
以及postXXX()
最終都會呼叫enqueueMessage()
方法,該方法則呼叫queue.enqueueMessage()
方法將訊息新增到訊息佇列。關於訊息佇列如何管理訊息可以看MessageQueue的佇列管理一文。
移除訊息removeMessage()
所有的removeMessages()
過載與removeCallbacks()
過載最終都是呼叫mQueue.removeMessages()
方法,即通過MessageQueue來實現該操作。詳細分析可以看MessageQueue的佇列管理一文。
處理訊息dispatchMessage()
訊息處理最開始被呼叫的不是handleXXX()
方法,而是dispatchMessage()
方法。該方法會根據訊息是否有callback
來判斷該交給handleCallback()
還是handleMessage()
。前者直接呼叫引數中message
的message.calback.run()
解決問題,後者則是空方法體,需要我們開發者自己重寫。
Handler一些特點
handler可以分發Message物件和Runnable物件到主執行緒中, 每個Handler例項,都會繫結到建立他的執行緒中(一般是位於主執行緒),它有兩個作用:
- (1)安排訊息或Runnable 在某個主執行緒中某個地方執行;
- (2)安排一個動作在不同的執行緒中執行。
Handler例項
子類需要繼承Hendler類,並重寫handleMessage(Message msg) 方法, 用於接受執行緒資料。
以下為一個例項,它實現的功能為:通過執行緒修改介面Button的內容
public class MyHandlerActivity extends Activity { Button button; MyHandler myHandler; protected void onCreate(Bundle savedInstanceState) { super。onCreate(savedInstanceState); setContentView(R。layout。handlertest); button = (Button) findViewById(R。id。button); myHandler = new MyHandler(); // 當建立一個新的Handler例項時, 它會繫結到當前執行緒和訊息的佇列中,開始分發資料 // Handler有兩個作用, (1) : 定時執行Message和Runnalbe 物件 // (2): 讓一個動作,在不同的執行緒中執行。 // 它安排訊息,用以下方法 // post(Runnable) // postAtTime(Runnable,long) // postDelayed(Runnable,long) // sendEmptyMessage(int) // sendMessage(Message); // sendMessageAtTime(Message,long) // sendMessageDelayed(Message,long) // 以上方法以 post開頭的允許你處理Runnable物件 //sendMessage()允許你處理Message物件(Message裡可以包含資料,) MyThread m = new MyThread(); new Thread(m)。start(); } /** * 接受訊息,處理訊息 ,此Handler會與當前主執行緒一塊執行 * */ class MyHandler extends Handler { public MyHandler() { } public MyHandler(Looper L) { super(L); } // 子類必須重寫此方法,接受資料 @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub Log。d("MyHandler", "handleMessage。。。。。。"); super。handleMessage(msg); // 此處可以更新UI Bundle b = msg。getData(); String color = b。getString("color"); MyHandlerActivity。this。button。append(color); } } class MyThread implements Runnable { public void run() { try { Thread。sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e。printStackTrace(); } Log。d("thread。。。。。。。", "mThread。。。。。。。。"); Message msg = new Message(); Bundle b = new Bundle();// 存放資料 b。putString("color", "我的"); msg。setData(b); MyHandlerActivity。this。myHandler。sendMessage(msg); // 向Handler傳送訊息,更新UI } } }複製程式碼
如果你覺
得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部