「Android」消息驅動Looper和Handler類分析

Android系統中的消息驅動工做原理:java

一、有一個消息隊列,能夠往這個消息隊列中投遞消息;android

二、有一個消息循環,不斷的從消息隊列中取得消息,而後處理。函數

 

工做流程:oop

一、事件源將待處理的消息加入到消息隊列中,通常是加至隊列尾部(優先級高的消息能夠加至隊列頭),事件源提交的消息能夠是按鍵、觸摸等物理事件產生的消息,也能夠是系統或應用程序發出的消息;this

二、處理線程不斷的從消息隊列頭中取出消息並處理。spa

 

在Android系統中,這些工做主要由LooperHandler實現:線程

Looper類,用於封裝消息循環,而且有一個消息隊列;code

Handler類,封裝消息投遞、消息處理等接口。對象

 

1、Looper類分析

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),該類有兩個關鍵函數:

  • set:設置調用線程的局部變量
  • get:獲取調用線程的局部變量

  所以,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。 

 

2、Handler類分析

  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函數)   

相關文章
相關標籤/搜索