成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android中消息機制簡述

移動開發 Android
Handler的處理過程運行在創建Handler的線程里,一個Looper對應一個MessageQueue,一個線程對應一個Looper,一個Looper可以對應多個Handler,不確定當前線程時,更新UI時盡量調用post方法。

前幾天,和同事探討了一下Android中的消息機制,探究了消息的發送和接收過程以及與線程之間的關系。雖然我們經常使用這些基礎的東西,但對于其內部原理的了解,能使我們更加容易、合理地架構系統,并避免一些低級錯誤。

Android中的Handler, Looper, MessageQueue和Thread,對于這部分的內容,將分成4小節來描述:

1.職責與關系

2.消息循環

3.線程與更新

4.幾點小結

1) 接下來,我們開始這部分的內容,首先了解一下各自的職責及相互之間的關系。

職責

Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。

Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。

MessageQueue:消息隊列,用來存放Handler發送過來的消息,并按照FIFO規則執行。當然,存放Message并非實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。

Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。

Thread:線程,負責調度整個消息循環,即消息循環的執行場所。

關系

Handler,Looper和MessageQueue就是簡單的三角關系。Looper和MessageQueue一一對應,創建一個Looper的同時,會創建一個MessageQueue。而Handler與它們的關系,只是簡單的聚集關系,即Handler里會引用當前線程里的特定Looper和MessageQueue。

這樣說來,多個Handler都可以共享同一Looper和MessageQueue了。當然,這些Handler也就運行在同一個線程里。

2) 接下來,我們簡單地看一下消息的循環過程:

生成

  1. Message msg = mHandler.obtainMessage(); 
  2.  
  3. msg.what = what; 
  4.  
  5. msg.sendToTarget(); 

發送

  1. MessageQueue queue = mQueue; 
  2.  
  3.  if (queue != null) { 
  4.  
  5.      msg.target = this
  6.  
  7.      sent = queue.enqueueMessage(msg, uptimeMillis); 
  8.  
  9.  } 

在Handler.java的sendMessageAtTime(Message msg, long uptimeMillis)方法中,我們看到,它找到它所引用的MessageQueue,然后將Message的target設定成自己(目的是為了在處理消息環節,Message能找到正確的Handler),再將這個Message納入到消息隊列中。

抽取

  1. Looper me = myLooper(); 
  2.  
  3. MessageQueue queue = me.mQueue; 
  4.  
  5. while (true) { 
  6.  
  7.     Message msg = queue.next(); // might block 
  8.  
  9.     if (msg != null) { 
  10.  
  11.         if (msg.target == null) { 
  12.  
  13.             // No target is a magic identifier for the quit message. 
  14.  
  15.             return
  16.  
  17.         } 
  18.  
  19.         msg.target.dispatchMessage(msg); 
  20.  
  21.         msg.recycle(); 
  22.  
  23.     } 
  24.  

在Looper.java的loop()函數里,我們看到,這里有一個死循環,不斷地從MessageQueue中獲取下一個(next方法)Message,然后通過Message中攜帶的target信息,交由正確的Handler處理(dispatchMessage方法)。

處理

  1. if (msg.callback != null) { 
  2.  
  3.     handleCallback(msg); 
  4.  
  5. else { 
  6.  
  7.     if (mCallback != null) { 
  8.  
  9.         if (mCallback.handleMessage(msg)) { 
  10.  
  11.             return
  12.  
  13.         } 
  14.  
  15.     } 
  16.  
  17.     handleMessage(msg); 
  18.  

在Handler.java的dispatchMessage(Message msg)方法里,其中的一個分支就是調用handleMessage方法來處理這條Message,而這也正是我們在職責處描述使用Handler時需要實現handleMessage(Message msg)的原因。

至于dispatchMessage方法中的另外一個分支,我將會在后面的內容中說明。

至此,我們看到,一個Message經由Handler的發送,MessageQueue的入隊,Looper的抽取,又再一次地回到Handler的懷抱。而繞的這一圈,也正好幫助我們將同步操作變成了異步操作。

3)剩下的部分,我們將討論一下Handler所處的線程及更新UI的方式

在主線程(UI線程)里,如果創建Handler時不傳入Looper對象,那么將直接使用主線程(UI線程)的Looper對象(系統已經幫我們創建了);在其它線程里,如果創建Handler時不傳入Looper對象,那么,這個Handler將不能接收處理消息。在這種情況下,通用的作法是

  1. class LooperThread extends Thread { 
  2.                public Handler mHandler; 
  3.                public void run() { 
  4.                               Looper.prepare(); 
  5.                               mHandler = new Handler() { 
  6.  
  7.                                             public void handleMessage(Message msg) { 
  8.                                                             // process incoming messages here 
  9.                                                } 
  10.                                }; 
  11.                               Looper.loop(); 
  12.                } 

在創建Handler之前,為該線程準備好一個LooperLooper.prepare),然后讓這個Looper跑起來(Looper.loop),抽取Message,這樣,Handler才能正常工作。

因此,Handler處理消息總是在創建Handler的線程里運行。而我們的消息處理中,不乏更新UI的操作,不正確的線程直接更新UI將引發異常。因此,需要時刻關心Handler在哪個線程里創建的。

如何更新UI才能不出異常呢?SDK告訴我們,有以下4種方式可以從其它線程訪問UI線程:

·      Activity.runOnUiThread(Runnable)

·      View.post(Runnable)

·      View.postDelayed(Runnable, long)

·      Handler

其中,重點說一下的是View.post(Runnable)方法。在post(Runnable action)方法里,View獲得當前線程(即UI線程)的Handler,然后將action對象post到Handler里。在Handler里,它將傳遞過來的action對象包裝成一個Message(Message的callback為action),然后將其投入UI線程的消息循環中。在Handler再次處理該Message時,有一條分支(未解釋的那條)就是為它所設,直接調用runnable的run方法。而此時,已經路由到UI線程里,因此,我們可以毫無顧慮的來更新UI。

4) 幾點小結

·      Handler的處理過程運行在創建Handler的線程里

·      一個Looper對應一個MessageQueue

·      一個線程對應一個Looper

·      一個Looper可以對應多個Handler

·      不確定當前線程時,更新UI時盡量調用post方法

責任編輯:閆佳明 來源: cnblogs
相關推薦

2011-05-31 11:55:00

Android 消息機制

2014-03-04 15:28:32

iOS開發消息傳遞機制

2010-02-25 15:49:05

WCF消息模式

2013-03-28 09:07:37

Android開發Intent機制

2017-05-15 19:40:40

AndroidIPC機制

2019-07-25 13:13:25

AndroidHandler消費機制

2016-03-02 09:34:03

runtime消息ios開發

2021-11-24 08:33:09

Android廣播機制應用程序

2010-05-21 18:15:41

MySQL 備份

2017-12-18 11:09:45

消息轉發DemoPerson

2024-09-25 08:32:05

2013-03-28 16:12:12

Message機制應用

2014-05-22 15:00:16

Android消息處理機制Looper

2014-05-22 15:04:00

Android消息處理機制Looper

2014-05-22 15:07:44

Android消息處理機制Looper

2014-05-22 15:38:27

Android消息處理機制Looper

2014-05-22 15:48:50

Android消息處理機制Looper

2014-05-22 15:41:59

Android消息處理機制Looper

2014-05-22 14:57:28

Android消息處理機制Looper

2014-05-22 15:15:53

Android消息處理機制Looper
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费国产网站 | 青春草91 | 日韩手机视频 | 国产成人精品久久二区二区91 | 亚洲精品国产成人 | 91免费看片 | 国产成人在线视频免费观看 | 国产视频一二三区 | 国产视频一区二区 | 精品成人免费一区二区在线播放 | 欧美极品在线观看 | 青青久久 | 免费在线观看成年人视频 | 亚洲天堂999 | 免费性视频 | 99热这里有精品 | 日韩久久综合 | 久综合 | 婷婷精品 | 国产在线一级片 | 99精品久久久久 | 国产精品揄拍一区二区 | 一区二区中文 | 国产又色又爽又黄又免费 | 亚洲视频www | 日韩中文字幕 | 成人免费在线观看 | 国产精品天堂 | 午夜a√ | 日日干综合| 欧美精品福利视频 | 国产精品久久久久久久久久久久冷 | 91p在线观看 | 亚洲成人午夜在线 | 日韩一区二区视频 | 三极网站 | 亚洲国产一 | 在线一区视频 | 久久9热 | 中国一级特黄毛片大片 | 亚洲 成人 av |