一、什么是handler?
handler是Android給我們提供用來更新UI的一套機制,也是一套消息處理機制,我們可以發消息,也可以通過它 處理消息。
二、那為什么要用handler呢?我能不能不用?
肯定是不行的。因為android在設計的時候就封裝了一套消息創建、傳遞、處理。如果不遵循就不能更新UI信息,就會報出異常。
三、Android為什么要設計只能用handler機制更新UI呢?
最根本的目的就是為了解決多線程并發的問題!
? ? ? ? ? ?打個比方,如果在一個activity中有多個線程,并且沒有加鎖,就會出現界面錯亂的問題。但是如果對這些更新UI的操作都加鎖處理,又會導致性能下降。
? ? ? ? ? 處于對性能的問題考慮,Android給我們提供這一套更新UI的機制我們只需要遵循這種機制就行了。不用再去關系多線程的問題,所有的更新UI的操作,都是在主線程的消息隊列中去輪訓的。
四、handler中send和post方法的區別
在Android中handler用來進行進程間通信,其中有send和post兩種方法,大家常用的send方法,其是在工作線程中處理完耗時操作后調用handler的sendMessage(message)把message對象發送給主線程,在主線程中重寫handlerMessage()方法,判斷接收到的消息進行更新UI的操作;而post方法傳遞的是一個runnable對象,更新UI的操作也是在這個runnable的run方法中進行的,也就是說run方法中的代碼是執行在主線程中的,雖然它是寫在工作線程中,主線程在接收到消息后自動執行runnable的run方法中的代碼。
public class MainActivity extends Activity {
??? private Button btSend;
??? private Button btPost;
??? private TextView textview;
??? private static final int SEND_UPDATA_TEXT=0;
??? private Handler handler=new Handler(){
?? ??? ?public void handleMessage(Message msg) {
?? ??? ??? ?switch (msg.what) {
?? ??? ??? ?case SEND_UPDATA_TEXT:
?? ??? ??? ??? ?textview.setText("sendMessage發來的消息");
?? ??? ??? ??? ?break;
?? ??? ??? ?default:
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ?};
??? };
?? ?@Override
?? ?protected void onCreate(Bundle savedInstanceState) {
?? ??? ?super.onCreate(savedInstanceState);
?? ??? ?setContentView(R.layout.activity_main);
?? ??? ?//初始化控件
?? ??? ?setViews();
?? ??? ?//事件監聽
?? ??? ?setListener();
?? ?}
?? ?private void setListener() {
?? ??? btSend.setOnClickListener(new OnClickListener() {
?? ??? ?@Override
?? ??? ?public void onClick(View v) {
?? ??? ??? ?new Thread(new Runnable() {
?? ??? ??? ??? ?@Override
?? ??? ??? ??? ?public void run() {
?? ??? ??? ??? ??? ?Message message=new Message();
?? ??? ??? ??? ??? ?message.what=SEND_UPDATA_TEXT;
?? ??? ??? ??? ??? ?handler.sendMessage(message);
?? ??? ??? ??? ?}
?? ??? ??? ?}).start();
?? ??? ?}
?? ?});
?? ??? btPost.setOnClickListener(new OnClickListener() {
?? ??? ?@Override
?? ??? ?public void onClick(View v) {
?? ??? ??? ?new Thread(new Runnable() {
?? ??? ??? ??? ?@Override
?? ??? ??? ??? ?public void run() {
?? ??? ??? ??? ??? ?//使用post發送消息
?? ??? ??? ??? ??? ?handler.post(new Runnable() {
?? ??? ??? ??? ??? ??? ?//run方法中的代碼執行在UI線程中
?? ??? ??? ??? ??? ??? ?@Override
?? ??? ??? ??? ??? ??? ?public void run() {
?? ??? ??? ??? ??? ??? ??? ?textview.setText("post發來消息");
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?});
?? ??? ??? ??? ?}
?? ??? ??? ?}).start();
?? ??? ?}
?? ?});
?? ?}
?? ?private void setViews() {
?? ??? ?btSend=(Button) findViewById(R.id.bt_send);
?? ??? ?btPost=(Button) findViewById(R.id.bt_post);
?? ??? ?textview=(TextView) findViewById(R.id.textview);
?? ?}
}
源碼流程分析
handler 發送Message(消息)至MessageQueue(模擬隊列),由Looper(循環器)不斷的循環取出,然后通知handler處理消息,這是整個消息機制
Looper 消息輪訓器
MessageQueue消息暫存隊列(單鏈表結構)
Message 消息
Handler 收發消息工具
請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關系。
答:簡單的說,Handler獲取當前線程中的looper對象,looper用來從存放Message的MessageQueue中取出Message,再有Handler進行Message的分發和處理.
Message Queue(消息隊列)/8:用來存放通過Handler發布的消息,通常附屬于某一個創建它的線程,可以通過Looper.myQueue()得到當前線程的消息隊列
Handler:可以發布或者處理一個消息或者操作一個Runnable,通過Handler發布消息,消息將只會發送到與它關聯的消息隊列,然也只能處理該消息隊列中的消息
Looper:是Handler和消息隊列之間通訊橋梁,程序組件首先通過Handler把消息傳遞給Looper,Looper把消息放入隊列。Looper也把消息隊列里的消息廣播給所有的
Handler:Handler接受到消息后調用handleMessage進行處理
Message:消息的類型,在Handler類中的handleMessage方法中得到單個的消息進行處理
在單線程模型下,為了線程通信問題,Android設計了一個Message Queue(消息隊列), 線程間可以通過該Message Queue并結合Handler和Looper組件進行信息交換。下面將對它們進行分別介紹:
1)?Message
?Message消息,理解為線程間交流的信息,處理數據后臺線程需要更新UI,則發送Message內含一些數據給UI線程。
2)?Handler
?Handler處理者,是Message的主要處理者,負責Message的發送,Message內容的執行處理。后臺線程就是通過傳進來的 Handler對象引用來sendMessage(Message)。而使用Handler,需要implement 該類的 handleMessage(Message)方法,它是處理這些Message的操作內容,例如Update UI。通常需要子類化Handler來實現handleMessage方法。
3)?Message Queue
?Message Queue消息隊列,用來存放通過Handler發布的消息,按照先進先出執行。
?每個message queue都會有一個對應的Handler。Handler會向message queue通過兩種方法發送消息:sendMessage或post。這兩種消息都會插在message queue隊尾并按先進先出執行。但通過這兩種方法發送的消息執行的方式略有不同:通過sendMessage發送的是一個message對象,會被 Handler的handleMessage()函數處理;而通過post方法發送的是一個runnable對象,則會自己執行。
4)?Looper
?Looper是每條線程里的Message Queue的管家。Android沒有Global的Message Queue,而Android會自動替主線程(UI線程)建立Message Queue,但在子線程里并沒有建立Message Queue。所以調用Looper.getMainLooper()得到的主線程的Looper不為NULL,但調用Looper.myLooper() 得到當前線程的Looper就有可能為NULL。對于子線程使用Looper,API Doc提供了正確的使用方法:這個Message機制的大概流程:
?①在Looper.loop()方法運行開始后,循環地按照接收順序取出Message Queue里面的非NULL的Message。
② 一開始Message Queue里面的Message都是NULL的。當Handler.sendMessage(Message)到Message Queue,該函數里面設置了那個Message對象的target屬性是當前的Handler對象。隨后Looper取出了那個Message,則調用 該Message的target指向的Hander的dispatchMessage函數對Message進行處理。在dispatchMessage方法里,如何處理Message則由用戶指定,三個判斷,優先級從高到低:
a)?Message里面的Callback,一個實現了Runnable接口的對象,其中run函數做處理工作;
b)?Handler里面的mCallback指向的一個實現了Callback接口的對象,由其handleMessage進行處理;
c)?處理消息Handler對象對應的類繼承并實現了其中handleMessage函數,通過這個實現的handleMessage函數處理消息。
?由此可見,我們實現的handleMessage方法是優先級最低的!
?③ Handler處理完該Message (update UI) 后,Looper則設置該Message為NULL,以便回收!
?在網上有很多文章講述主線程和其他子線程如何交互,傳送信息,最終誰來執行處理信息之類的,個人理解是最簡單的方法——判斷Handler對象里面的Looper對象是屬于哪條線程的,則由該線程來執行!
①當Handler對象的構造函數的參數為空,則為當前所在線程的Looper;
②Looper.getMainLooper()得到的是主線程的Looper對象,Looper.myLooper()得到的是當前線程的Looper對象。
來講講一下handler機制
一個允許你發送和處理Message和Runable對象,每個線程都有自己的Looper,每個Looper中封裝著MessageQueue。Looper負責不斷的從自己的消息隊列里取出隊頭的任務或消息執行。每個handler也和線程關聯,Handler負責把Message和Runable
對象傳遞給MessageQueue(用到post,sendMessage等方法),而且在這些對象離開MessageQueue時,Handler負責執行他們(用到handleMessage方法)。
其中Message類就是定義了一個信息,這個信息中包含一個描述符和任意的數據對象,這個信息被用來傳遞給Handler.Message對象