android消息處理——Thread、Looper、Handler

一 簡介:

       android應用程序和windows程序一樣,都是基於消息驅動的。如果想要了解android系統的消息處理機制,理解Thread、Looper和Handler三個對象必不可少。Android系統中Looper負責管理線程的消息隊列和消息循環,即接受線程中的Message並分發、回調處理消息的函數。對於開發者來說,Looper本身可能不太重要,畢竟這個是android系統自身在管理,然而Handler就不一樣啦!我們知道在windows程序開發中,通過HWND的sendMssage函數發送特定的Message(系統或者自定義),並在HWND所屬的界面類中通過PreTranslateMessage、onMessage等函數進行處理,而在android系統是要通過Handler來實現這一功能。Handler可看做是Looper的一個接口,必須依附於特定的Looper存在,開發者通過sendMessage/sendEmptyMessage/sendMessageAtTime等函數向關聯Looper發送消息,在Handler的handleMessage中處理這些消息(需要用戶進行重寫)。與windows程序開發不同的是,Handler消息的發送與處理並不一定實在界面相關的類中完成,比較靈活!

二 Looper介紹
       Looper類管理線程的消息隊列和消息循環,具體來說是爲一個線程開啓一個消息循環,Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。而一個Looper對象可以對應多個線程,比如主線程的mainLooper,供主線程和所屬子線程共同使用。
       創建Handler時會與其被定義時所在線程的Looper綁定,比如,在主線程中定義,其是與主線程的Looper綁定:
       mainHandler = new Handler() 等價於new Handler(Looper.myLooper()).
      注:Looper.myLooper():Return the Looper object associated with the current thread 獲取當前線程的looper對象。還有一個類似的 Looper.getMainLooper() 用於獲取主線程的Looper對象。

三、Thread中設置自身的Looper
       Android系統的消息隊列和消息循環都是針對具體線程的,Thread可以有(也可以沒有)自己的Looper,即該線程自身可以維護一個Message隊列和消息循環,非主線程如果沒有設置自己的Looper,就和主線程共享一個消息隊列和消息循環(主線程一定關聯Looper,在應用程序啓動時由系統創建)。特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。如果想讓非主線程具有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然後調用Looper.loop()進入消息循環。如下例所示:

 class LooperThread extends Thread {
      public Handler mHandler;
      public void run() {
          Looper.prepare();
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          Looper.loop();
      }
  }
      這樣你的線程就具有了消息處理機制了,在Handler中進行消息處理。上面的代碼如果沒有設置Looper,直接在線程中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()
      即Handler必須依賴於特定的Looper。Looper.loop函數會使run函數停留在調用處,直到主動調用線程終止函數或者Looper對象的quit函數才能退出。

      一個 Activity中可以創建多個工作線程或者其他的組件,如果這些線程或者組件把他們的消息放入Activity的主線程消息隊列,那麼該消息就會在主線程中處理了。因爲主線程一般負責界面的更新操作,並且Android系統中的weget不是線程安全的,所以這種方式可以很好的實現Android界面更新。在Android系統中這種方式有着廣泛的運用。如上面介紹,其它非主線程通過Handle對象(Handler對象以主線程的Looper創建),那麼調用Handler的sendMessage等接口,將會把消息放入隊列都將是放入主線程的消息隊列。並且將會在Handler主線程中調用該handler 的handleMessage接口來處理消息。

      更詳細的內容參考:http://blog.csdn.net/dywe_ddm/article/details/5930948、http://www.android123.com.cn/androidkaifa/422.html、http://hi.baidu.com/donghaozheng/blog/item/d963d7333e39844dac4b5f1b.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章