Android中的Looper類,是用來封裝訊息迴圈和訊息佇列的一個類,用於在android線程中進行訊息處理。handler其實可以看做是一個工具類,用來向訊息佇列中插入訊息的。
(1) Looper類用來為一個線程開啟一個訊息迴圈。
預設情況下android中新誕生的線程是沒有開啟訊息迴圈的。(主線程除外,主線程系統會自動為其建立Looper對象,開啟訊息迴圈。)
Looper對象通過MessageQueue來存放訊息和事件。一個線程只能有一個Looper,對應一個MessageQueue。
(2) 通常是通過Handler對象來與Looper進行互動的。Handler可看做是Looper的一個介面,用來向指定的Looper發送訊息及定義處理方法。
預設情況下Handler會與其被定義時所線上程的Looper綁定,比如,Handler在主線程中定義,那麼它是與主線程的Looper綁定。
mainHandler = new Handler() 等價於new Handler(Looper.myLooper()).
Looper.myLooper():擷取當前進程的looper對象,類似的 Looper.getMainLooper() 用於擷取主線程的Looper對象。
(3) 在非主線程中直接new Handler() 會報如下的錯誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has
not called Looper.prepare()
原因是非主線程中預設沒有建立Looper對象,需要先調用Looper.prepare()啟用Looper。
(4) Looper.loop(); 讓Looper開始工作,從訊息佇列裡取訊息,處理訊息。
注意:寫在Looper.loop()之後的代碼不會被執行,這個函數內部應該是一個迴圈,當調用mHandler.getLooper().quit()後,loop才會中止,其後的代碼才能得以運行。
(5) 基於以上知識,可實現主線程給子線程(非主線程)發送訊息。
把下面例子中的mHandler聲明成類成員,在主線程通過mHandler發送訊息即可。
Looper用於在android線程中進行訊息處理,預設情況下,一個線程並不和任何Looper綁定。當我們調用Looper.prepare()時,如果當前線程還沒有和任何Looper綁定,那麼將建立一個Looper讓它和當前線程綁定。當我們調用Looper.loop()時,它將對當前線程所對應的Looper的訊息進行處理,從訊息佇列裡取訊息,處理訊息,一直迴圈直到對該Looper調用quit()函數。
注意:Looper.loop()中是個while迴圈,只有對它所線上程的Looper調用了quit()函數,Looper.loop()函數才能完成,其後的代碼才能得以運行。一個線程對應一個Looper,一個Looper對應一個訊息佇列MessageQueue。
對於Handler,其實只是把訊息發送到其對應的Looper的訊息佇列MessageQueue中,最後的處理還是在Looper.loop()的while迴圈中進行的。一個Looper可以用於構造多個Handler。因為Looper.loop()函數是個while迴圈,會讓當前線程一直在那裡處理進行迴圈,直到對該線程的Looper調用了quit()函數,所以,如果想對該Handler發送訊息或添加Runnable以進行交易處理,要麼在別的線程中進行,要麼在該Handler在處理訊息時或在Runnable()的run()函數中進行交易處理時進行。
注意:Handler的建構函式Handler()和Handler(Handler.Callback callback),雖然沒有Looper參數,但是它實際上是通過Looper.myLooper()來擷取當前線程中的Looper的。
以下是Android API中的一個典型的Looper thread實現