handler looper和messageQueue,loopermessagequeue
一、使用方法。
Looper用來處理訊息迴圈,在建立過程中會初始化MessageQueue。
Handler在其它線程發訊息給當前線程
MessageQueue用來存放訊息
Looper對象在哪個線程建立,Handler的handleMessage方法就在哪個線程執行
在建立activity時,android系統本身會為activity建立Looper。
final Handler mainHandler = new Handler(getMainLooper()){@Overridepublic void handleMessage(Message msg){String content = "當前線程:" + "msg:" + msg.what;Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();}};mainHandler.sendEmptyMessage(0x1);在其它線程中使用handler訊息傳遞時,必須自己建立looper。下面的例子中HandlerThread封裝了Looper和MessageQueue,還實現了擷取Looper的同步機制,比較好用。
HandlerThread mThread = new HandlerThread("MyThread");mThread.start();Handler mHandle = new Handler(mThread.getLooper()){@Overridepublic void handleMessage(Message msg){String content = "當前線程:" + Thread.currentThread().getName() + "msg:" + msg.what;System.out.println(content);}};mHandle.sendEmptyMessage(0x2);
二、Looper解析
建構函式:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread();}public static void prepare() { prepare(true);}private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));}在prepare中建立了Looper執行個體,並在Looper的建構函式中建立了MessageQueue
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger msg.target.dispatchMessage(msg); // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); msg.recycle(); }}
在loop()中,Looper不斷的通過queue.next()從MessageQueue取訊息,然後調用語句msg.target.dispatchMessage(msg) 來執行。這裡target為msg訊息的寄件者Handler,在分析Handler時再來分析,dispatchMessage在一般情況下會調用Handler類的handleMessage來處理訊息,也就是上面例子中我們重載的這個handleMessage。
三、Handler解析
Handler的建構函式有很多,這裡選帶Looper參數的建構函式
public Handler(Looper looper) { this(looper, null, false);}public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}
再看sendMessage。
public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis);}public final boolean sendMessageDelayed(Message msg, long delayMillis){ if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
sendEmptyMessage將message加到了Looper的MessageQueue中,之後Looper在loop()中調用queue.next()
在enqueueMessage裡面,我們看到了msg.target = this
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
如果沒有設定Callback的話,就會運行handleMessage了。
四、HandlerThread解析
HandlerThread繼承於Thread,對Looper的操作進行了封裝,做了同步處理。
public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1;}public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper;}
Android Handler機制 怎使用?
Handler對象與其調用者在同一線程中,如果在Handler中設定了延時操作,則調用線程也會堵塞。每個Handler對象都會綁定一個Looper對象,每個Looper對象對應一個訊息佇列(MessageQueue)。如果在建立Handler時不指定與其綁定的Looper對象,系統預設會將當前線程的Looper綁定到該Handler上。
在主線程中,可以直接使用new Handler()建立Handler對象,其將自動與主線程的Looper對象綁定;在非主線程中直接這樣建立Handler則會報錯,因為Android系統預設情況下非主線程中沒有開啟Looper,而Handler對象必須綁定Looper對象。這種情況下,需先在該線程中手動開啟Looper(Looper.prepare()-->Looper.loop()),然後將其綁定到Handler對象上;或者通過Looper.getMainLooper(),獲得主線程的Looper,將其綁定到此Handler對象上。
Handler發送的訊息都會加入到Looper的MessageQueue中。一說Handler包含兩個隊列:線程隊列和訊息佇列;使用Handler.post()可以將線程對象加入到線程隊列中;使用Handler.sendMessage()可以將訊息對象加入到訊息佇列中。通過源碼分析證實,Handler只有一個訊息佇列,即MessageQueue。通過post()傳進去的線程對象將會被封裝成訊息對象後傳入MessageQueue。
使用post()將線程對象放到訊息佇列中後,當Looper輪詢到該線程執行時,實際上並不會單獨開啟一個新線程,而仍然在當前Looper綁定的線程中執行,Handler只是調用了該線程對象的run()而已。如,在子線程中定義了更新UI的指令,若直接開啟將該線程執行,則會報錯;而通過post()將其加入到主線程的Looper中並執行,就可以實現UI的更新。
使用sendMessage()將訊息對象加入到訊息佇列後,當Looper輪詢到該訊息時,就會調用Handler的handleMessage()來對其進行處理。再以更新UI為例,使用這種方法的話,就先將主線程的Looper綁定在Handler對象上,重載handleMessage()來處理UI更新,然後向其發送訊息就可以了。
android開發中對於handler部分的困惑
這麼說吧,handler是一個訊息佇列,其中就有這個Message 當你new了一個handler的時候同時就攜帶了一個Message對象!當你需要傳遞資訊的時候直接拿就ok了。同時建議你看一下啊Handler 的機制原理
(給你列舉一下算了):
andriod提供了 Handler 和 Looper 來滿足線程間的通訊。Handler 先進先出原則。Looper類用來管理特定線程內對象之間的訊息交換(Message Exchange)。
1)Looper: 一個線程可以產生一個Looper對象,由它來管理此線程裡的Message Queue(訊息佇列)。
2)Handler: 你可以構造Handler對象來與Looper溝通,以便push新訊息到Message Queue裡;或者接收Looper從Message Queue取出)所送來的訊息。
3) Message Queue(訊息佇列):用來存放線程放入的訊息。
4)線程:UI thread 通常就是main thread,而Android啟動程式時會替它建立一個Message Queue。