handler looper和messageQueue,loopermessagequeue

來源:互聯網
上載者:User

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。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.