Handler訊息機制

2021-09-27 10:49:16 字數 2796 閱讀 3060

android的訊息機制主要是指handler的執行機制,也就是handler、message、messagequeue、looper、threadlocal之間的工作過程。

handler:主要用於傳送和處理訊息。

messagequeue:訊息佇列,主要用於存放所有通過handler傳送的message,每個執行緒中只會有乙個messagequeue物件。

looper:迴圈器,呼叫looper.loop()方法後,就會進入無限迴圈中,每當發現messagequeue中有新訊息後就會把它取出來傳遞到handler中去處理,每個執行緒中只有乙個looper物件。

threadlocal:儲存一些以執行緒為作用域的資料,執行緒內部獲取到的儲存資料是唯一的,不同執行緒獲取到的儲存資料是不同的。

messagequeue

messagequeue主要包含enqueuemessage()插入和next()讀取兩個操作,執行讀取操作的時候會把讀取到的message從messagequeue中刪除。messagequeue的內部是通過乙個單鏈表的資料結構來維護的。

enqueuemessage():主要操作是在這個單鏈表中儲存message。

next():是乙個無限迴圈的方法,如果messagequeue中沒有訊息,就一直阻塞在那裡,當有新訊息來的時候,就會把新訊息返回並將該訊息從messagequeue中移除。

quit(boolean safe):將mquitting屬性置為true,這樣next()方法就會返回null。

looper

handler的工作需要looper,沒有looper的執行緒會報錯,我們通過looper.prepare()方法即可為當前執行緒建立乙個looper,然後通過looper.loop()開啟訊息迴圈。在looper的構造方法中我們可以看到,會建立乙個messagequeue物件,然後將當前執行緒儲存起來。

private looper(boolean quitallowed)
looper最重要的乙個方法是loop(),呼叫了loop()方法以後,訊息機制才真正的迴圈起來。在loop方法中,會呼叫messagequeue.next()方法取出一條訊息msg,msg為null則跳出迴圈,msg為null也是唯一跳出迴圈的方法。msg不為null,則會呼叫msg.target.dispatchmessage(msg)方法,msg.target是傳送這條訊息的handler物件,最終將訊息交給handler來處理了。

quit():呼叫messagequeue.quit(false)

quitsafely():呼叫messagequeue.quit(true)

handler

傳送訊息:

handler有兩種傳送訊息的方式,handler.sendmessage(message)和handler.post(runnable),post方法傳送訊息最終也是通過send方法完成的。可以看到,傳送訊息的過程調的是messagequeue.enqueuemessage(message)方法向單鏈表中插入一條訊息。

public final boolean post(runnable r)

public final boolean sendmessage(message msg)

public final boolean sendmessagedelayed(message msg, long delaymillis)

return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);

}public boolean sendmessageattime(message msg, long uptimemillis)

return enqueuemessage(queue, msg, uptimemillis);

}

處理訊息:

looper通過loop()方法接收到訊息後,會呼叫handler的dispatchmessage(message)方法。如果是通過post方法傳送的訊息,msg.callback!=null,最終會調run()方法處理訊息。如果是通過send方式傳送的訊息,會呼叫handlemessage()方法處理訊息。

public void dispatchmessage(message msg)  else 

}handlemessage(msg);

}} private static void handlecallback(message message)

mcallback!=null的情況是我們建立handler物件的時候是通過如下方式建立的

handler handler=new handler(new handler.callback()

});

在handler的構造方法中,會判斷當前執行緒中是否有looper,如果沒有looper會丟擲"can't create handler inside thread that has not called looper.prepare()",在主線程中我們沒有做這些操作是因為主線程已經幫我們做了這些操作。所以在子執行緒中建立handler的正確方式是:

new thread() 

};looper.loop();

}}.start();

傳送訊息過程流程圖:接收訊息過程流程圖:

Handler訊息傳遞機制

使用方法 1.若在ui主線程中,則系統已經初始化了乙個looper物件 因為主線程也是乙個訊息迴圈,因此具有乙個looper,主線程的所有工作都是由其looper完成的looper不斷從訊息佇列中抓取訊息,然後完成訊息指定的任務 否則要自己建立乙個looper物件並啟動。我們無法通過構造器建立loo...

Handler訊息傳遞機制

android中ui並不是執行緒安全的,什麼是執行緒安全呢 這是維基給出的解釋。如果有多個執行緒操作ui,會造成執行緒不安全問題。因此android有規定 ui元件只能在activity中對ui進行操作。當乙個程式第一次啟動時,android會同時啟動乙個main thread 主線程 主要負責與u...

訊息傳遞機制之Handler機制

在專案中,都會遇見執行緒之間通訊,元件之間通訊.在應用程式中,往往會有一些比較耗時的操作 為了防止阻塞主線程 會將耗時的操作放到子執行緒中執行 處理完成後再去更新ui 但是android不允許子執行緒操作ui 違背了android單執行緒模型的原則 即ui操作不是執行緒安全的而且這些操作必須放在ui...