Android系統中的消息驅動工做原理:java
一、有一個消息隊列,能夠往這個消息隊列中投遞消息;android
二、有一個消息循環,不斷的從消息隊列中取得消息,而後處理。函數
工做流程:oop
一、事件源將待處理的消息加入到消息隊列中,通常是加至隊列尾部(優先級高的消息能夠加至隊列頭),事件源提交的消息能夠是按鍵、觸摸等物理事件產生的消息,也能夠是系統或應用程序發出的消息;this
二、處理線程不斷的從消息隊列頭中取出消息並處理。spa
在Android系統中,這些工做主要由Looper和Handler實現:線程
Looper類,用於封裝消息循環,而且有一個消息隊列;code
Handler類,封裝消息投遞、消息處理等接口。對象
Looper用於封裝了android線程中的消息循環,默認狀況下一個線程是不存在消息循環(message loop)的,須要調用Looper.prepare()來給線程建立一個消息循環,調用Looper.loop()來使消息循環起做用,使用Looper.prepare()和Looper.loop()建立了消息隊列就可讓消息處理在該線程中完成。blog
class LooperThread extends Thread { public void run() { Looper.prepare(); //代碼1.... Looper.loop(); //代碼2.... } }
(1)在 Looper.prepare()中,定義一個ThreadLocal對象sT,並構造一個Looper對象設置到調用線程的局部變量sT中。
ThreadLocal是java中的線程局部變量類(Thread Local Variable),該類有兩個關鍵函數:
所以,prepareh函數會在調用線程的局部變量中設置一個Looper對象。這個調用線程就是LooperThread的run線程。
private Looper(){ //構造一個消息隊列 mQueue = new MessageQueue(); //獲得當前線程的Thread對象 mThread = Thread.currentThread(); }
prepare函數中設置了一個Looper對象,對象保存在這個調用線程的局部變量中。而Looper 對象內部封裝了一個消息隊列。
(2)Looper循環
> 在Loop()方法中,首先經過ThreadLocal的get方法獲取建立的Looper對象;
> 以後取出這個Looper的消息隊列 MessageQueue queue = looper.mQueue;
> while循環中,處理消息:
while(true){ Message msg = queue.next(); // 處理i消息,Message對象中有一個target(Handler類型) // 若是target爲空,則退出消息循環 if (msg != null ) { if (msg.target == null) { return; } // 調用該消息的Handler,交給他的dispatchMessage函數處理。 msg.target.dispatchMessage(msg); msg.recyle(); } }
所以,分析prepare和loop函數後,Looper的做用有:
一、封裝了一個消息隊列;
二、prepare函數把這個Looper和調用prepare的線程(最終的處理線程)關聯在i一塊兒;
三、處理線程調用loop函數,處理來自消息隊列的消息
當事件源向Looper發送消息時,消息加到Looper的消息隊列。該消息將由和Looper綁定的處理線程來處理。
注:Looper、Message、Handler的關係:
一、Looper中有一個Message隊列,存儲的時一個個待處理的message;
二、Message中有一個Handler,用來處理Message。
Handler中包括的成員:
Hadler.java:
final messageQueue mQueue; //Handler中也有一個消息隊列 final Looper mLooper; final Callback mCallback; //i回調用的類
在Handler的構造函數中,Handler中的消息隊列最終會指向Looper的消息隊列。
(1)插入消息到Looper消息隊列
Handler提供了一系列幫助完成建立消息和插入消息隊列的函數。
例如Handler.java中sendMessage發送一個消息,將消息添加到消息隊列末尾:
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean senMessageDelayed(Message msg, long delayMilis){ ...... return senMessage(msg, SystemClock.uptimeMillis() + delayMillis); // 當前時間 } public boolean sendMessageTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; // 將targt設置爲本身,而後加入到消息隊列 sent = queue.enqueueMessage(msg, uptimeMillis); } return sentl }
(2)Handler的消息處理
在loop方法中,若是得到消息後會調用target的dispatchMessage函數,而後將這個消息派發給Handler處理。
dispatchMessage定義了一套消息處理的優先級機制:
> Messagu若是自帶callback處理,則交給callback處理;
> Handler若是設置了全局的mCallback,則交給mCallback處理;
> 若是上述都沒有,消息則會被交給Handler子類實現的handleMessage 來處理。(這須要從Handler派生並重載handleMessage函數)