在Android開發中,使用消息隊列(message)完成線程間通訊。而使用消息隊列的線程就是消息循環(message looper)。消息循環不斷的檢查消息隊列,是否有新消息。消息循環是由一個線程和一個looper組成;looper對象管理着線程的消息隊列。app
Android的主線程也是一個消息循環,也具備一個Looper,主線程全部的任務都是由looper完成。消息循環是由一個線程和一個looper組成,looper對象管理着線程的消息隊列;所以,looper不斷的從消息隊列中抓取消息,而後完成消息指定的任務。函數
PS: 線程默認狀況下,是沒有消息循環(Looper)的,在Android中,只有主線程默認就是Looper(消息循環)。在新建立的線程中,使用Looper,要先建立一個Looper才行。oop
從下面圖中瞭解一下Runnable、Message、MessageQueue、Looper、Handler含義:spa
(此圖來自於其它書籍資料)線程
將這此含義揉合在一塊兒就是一個消息從發出到執行的整個過程:3d
(此圖來自於其它書籍資料)對象
從上面這兩個圖中,咱們能夠了解到:blog
1. Runnable和Message壓入到MessageQueue中,造成一個消息集合。繼承
2. Looper在不斷的循環,不停的在作某一件事,好比:上圖中Looper在不停的從MessageQueue中拿出Item,再傳遞給Handler執行。接口
3. Handler在不斷的去作某一具體的事情,好比:Handler收到一個消息,去解析一個後臺返回的數據,再將其更新到UI上。
從上面來看,Handler和Thread從表像上看確實沒有直接的關係,可是由於:
1. 每一個Thread只能對應一個Looper;
2. 每一個Looper只能對應一個MessageQueue;
3. 每一個MessageQueue有N個Message;
4. 每一個Message最多指定一個Handler來處理;
由此,能夠推出Thread和Handler是一對多的關係。而Handler有兩方面做用:
1. 處理Message,做爲Message處理者。
2. 負責將Message壓入MessageQueue中。
Message與Handler是成對出現的,Message是消息,而Handler是消息要完成任務的對象。
消息是Message的一個實例,在實現一個消息時,要同時實現Message類的一些實例變量,
Handler是完成消息或消息指定任務的對象,Handler不只是完成消息的目標或對象,也是建立和發佈消息(Message)的接口。
(圖來源於Android權威指南)
在看看下面這個圖,
(圖來源於Android權威指南)
從上面這個圖中,能夠看出,有多個Handler與一個Looper相關聯,這說明一個Handler的message與另外一個Handler的message放於同一個消息隊列。
1. 使用Handler.obtainMessage(...)方法會從公共循環消息隊列中,獲取message。
2. 使用Handler.sendToTarget()方法,會方法消息發送給與message相關聯的Handler。而Handler會將message放於Looper的消息隊列尾部。
3. Looper在消息隊列中,獲取到特定的消息後,將其發送給消息目標(與之相關聯的Handler)去處理。消息通常在Handler(消息目標)的handlerMessage(...)實現方法處理消息指定要完成的任務。通常,要繼承Handler基類,覆蓋handlerMessage()方法。
Handler類的一個實例,能夠做爲函數參數,傳遞給其它子線程。
主線程擁有一個Handler和Looper消息循環,在線程中,主線程上建立一個Handler,會自動與主線程的Looper相關聯。將主線程建立的Handler傳遞給另外一個子線程,傳遞出去的Handler始終會與建立它的線程的Looper保持聯繫。所以,任何已傳出的Handler負責處理的消息,都將在主線程的消息隊列中處理。
那麼,就能夠經過這種方式,在子線程中,去更新主線程的事件,數據,或者UI。
在主線程中不用建立Looper是由於App啓動時,建立主線程中默認建立了Looper,而且一個線程中,只能有一個Looper。存在多個系統會報錯。
Looper爲何不會堵塞主線程,提示ANR(application not responding)?
由於,主線程中的Activity和全部事件都是經過Looper執行的。Looper有一個消息隊列,在不斷的接收事件消息和執行事件。此中的堵塞是指Looper循環不被堵塞,而非Looper堵塞線程。