【轉載】每個 Android 開發人員必須知道的訊息機制問題總結

來源:互聯網
上載者:User

標籤:

Android的訊息機制幾乎是面試必問的話題,當然也並不是因為面試,而去學習,更重要的是它在Android的開發中是必不可少的,佔著舉足輕重的地位,所以弄懂它是很有必要的。下面就來說說最基本的東西。

Looper

作用:

  • 關聯起Thread
  • 迴圈取出訊息
1、Looper是否可以直接執行個體化?

Looper構造方法是私人的,其中做了兩件事

  • 建立一個MessageQueue
  • 得到與之對應的Thread
 private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}
2、一個線程能對應多個Lopper?

不能,一個線程對應一個Looper對象,通過ThreadLocal保證一個線程只有一個Looper與之對應,如果多次調用Looper.prepare();則會拋出運行時異常。

 private static void prepare(boolean quitAllowed) {   if (sThreadLocal.get() != null) { // 查看是否有looper與當前線程對應        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}
3、Looper是無限迴圈,會阻塞嗎?

是,當開啟一個loop後是一個死迴圈,從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;// 略    for (;;) {        Message msg = queue.next(); // might block        if (msg == null) { // 當沒有訊息的時候,退出            // No message indicates that the message queue is quitting.            return;        }// 略        msg.target.dispatchMessage(msg);   }
4、可以再次調用Looper.prepareMainLooper嗎?

不可以,Looper.prepareMainLooper最終也是調用prepare(),同2.

public static void prepareMainLooper() {    prepare(false); // 建立一個Looper    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}
5、MainLooper什麼時候建立的?

MainLooper是啟動Activity建立ActivityThread(並不是一個Thread)時候建立,所以不能多次建立。

public static void main(String[] args) {  // 略   Process.setArgV0("<pre-initialized>");  Looper.prepareMainLooper();  // 略  ActivityThread thread = new ActivityThread();  thread.attach(false);  // 略  if (sMainThreadHandler == null) {  sMainThreadHandler = thread.getHandler();  }  // 略  Looper.loop();  throw new RuntimeException("Main thread loop unexpectedly exited");  }}
Handler

作用:

  • 發送訊息到MessageQueue
  • 處理訊息
1、Handler如何與Looper、MessageQueue關聯起來?

我們知道一個Looper對應一個Thread,一個Looper包含一個MessageQueue。當我們建立Handler時就會從當前線程中取出與之對應的Looper,讓後在從Looper中取出MessageQueue。

// 1、自動擷取public Handler(Callback callback, boolean async) { // 略    mLooper = Looper.myLooper(); // 取出當前線程中的Looper    if (mLooper == null) {        throw new RuntimeException(            "Can‘t create handler inside thread that has not called Looper.prepare()");    }    mQueue = mLooper.mQueue; // 取出MessageQueue    mCallback = callback;    mAsynchronous = async;}// 2、傳遞一個Looper進來public Handler(Looper looper, Callback callback, boolean async) {        mLooper = looper;        mQueue = looper.mQueue;        mCallback = callback;        mAsynchronous = async;    }
Message

單項鏈表結構。

作用:

  • 資料的載體
1、訊息如何複用的?

從全域訊息池(鏈表結構)中

public static Message obtain() {   synchronized (sPoolSync) {        if (sPool != null) {            Message m = sPool;            sPool = m.next;            m.next = null;            m.flags = 0; // clear in-use flag            sPoolSize--;            return m;        }    }    return new Message();}
2、Message為什麼能傳遞?

Android中想要傳遞對象要麼實現Serializable要麼Parcelable,在這裡是實現了Parcelable介面。

public final class Message implements Parcelable {  // 略}
3、如何與Handler關聯?

我們知道在訊息傳機制中Handler充當著“快遞員”的角色,那麼他又是如何與“貨物”--Message發生關係呢?實際上Message有一個成員變數target他的類型正是Handler,

/*package*/ Runnable callback;public int arg1; public int arg2;public Object obj;/*package*/ Handler target; // 關鍵點

當我們通過Handler去send一個Message時候最終都會為target賦值為this,即當前的Handler。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {    msg.target = this; // 指派陳述式    if (mAsynchronous) {        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);}

另為如果是通過Message.Obtain(),擷取的複用Message也會為其賦值。

多說一句,Handler.obtainMessage()調用的就是Message.Obtain()。

public final Message obtainMessage(){    return Message.obtain(this);}
總結:

通過一系列的包涵關係,最終Looper、Handler、Message、MessageQueue即發生關聯,從而形成一個閉合,開啟訊息迴圈。

困惑

【轉載】每個 Android 開發人員必須知道的訊息機制問題總結

聯繫我們

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