Android中Message機(jī)制的靈活應(yīng)用
正式開始介紹Android開發(fā)中Message機(jī)制應(yīng)用,希望你有所收獲。
一、線程間通訊的Message機(jī)制
1、Message介紹
frameworks\base\core\java\android\Os\Message.java
Message是線程之間傳遞信息的載體,包含了對(duì)消息的描述和任意的數(shù)據(jù)對(duì)象。Message中包含了兩個(gè)額外的 int字段和一個(gè)object字段,這樣在大部分情況下,使用者就不需要再做內(nèi)存分配工作了。雖然Message的構(gòu)造函數(shù)是public的,但是***是 使用Message.obtain( )或Handler.obtainMessage( )函數(shù)來(lái)獲取Message對(duì)象,因?yàn)镸essage的實(shí)現(xiàn)中包含了回收再利用的機(jī)制,可以提供效率。
2、MessageQueue介紹
frameworks\base\core\java\android\Os\MessageQueue.java
MessageQueue用來(lái)容納Message隊(duì)列的,其中的Message是由Looper來(lái)分發(fā)的,Message不能直接添加到MessageQueue中,而是要通過(guò)與Looper關(guān)聯(lián)的Handler去添加。
3、Looper
frameworks\base\core\java\android\Os\Looper.java
Looper是線程用來(lái)運(yùn)行消息循環(huán)的。線程本身是沒(méi)有消息循環(huán)的,需要在線程中調(diào)用perpare函數(shù),然后調(diào)用loop去處理消息。在Android中,系統(tǒng)在啟動(dòng)主線程的時(shí)候會(huì)自動(dòng)為之建立一個(gè)Looper。
建立本線程的Looper:
public static final void prepare()
運(yùn)行本線程的Looper:
public static final void loop()
獲取本線程的Looper:
public static final Looper myLooper()
獲取主線程的Looper:
public synchronized static final Looper getMainLooper()
4、Handler
frameworks\base\core\java\android\Os\Handler.java
Handler是用來(lái)發(fā)送和處理與線程相關(guān)聯(lián)的Message和Runnable對(duì)象的。每個(gè)Handler都與一個(gè)單獨(dú)的線程以及線程消息隊(duì)列相 關(guān)聯(lián)的。當(dāng)你創(chuàng)建Handler時(shí),Handler就與線程以及線程消息隊(duì)列綁定了,從那以后,Handler就可以將 Message和Runnable發(fā)送給對(duì)應(yīng)的消息隊(duì)列,并且能夠處理從消息隊(duì)列中出來(lái)的消息。
Handler提供了用戶需要調(diào)用的大部分接口
A、創(chuàng)建Handler:
創(chuàng)建與本地線程相關(guān)聯(lián)的Handler:
public Handler()
public Handler(Callback callback)
創(chuàng)建與指定線程相關(guān)聯(lián)的Handler:
public Handler(Looper looper)
public Handler(Looper looper, Callback callback)
B、創(chuàng)建消息
- public final Message obtainMessage()
- public final Message obtainMessage(int what)
- public final Message obtainMessage(int what, Object obj)
- public final Message obtainMessage(int what, int arg1, int arg2)
- public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
C、刪除消息
刪除在消息隊(duì)列中未處理的消息
- public final void removeMessages(int what)
- public final void removeMessages(int what, Object object)
D、發(fā)送消息
- public final boolean sendMessage(Message msg)
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- public final boolean post(Runnable r)
- public final boolean postDelayed(Runnable r, long delayMillis)
E、處理消息
在Looper的loop函數(shù)中循環(huán)取出MessageQueue的接收消息隊(duì)列中的消息,然后調(diào)用Hander的dispatchMessage函數(shù)對(duì)消息進(jìn)行處理,至于如何處理(相應(yīng)消息)則由用戶指 定(三個(gè)方法,優(yōu)先級(jí)從高到低:Message里面的Callback,一個(gè)實(shí)現(xiàn)了Runnable接口的對(duì)象,其中run函數(shù)做處理工 作;Handler里面的mCallback指向的一個(gè)實(shí)現(xiàn)了Callback接口的對(duì)象,里面的handleMessage進(jìn)行處理;處理消息 Handler對(duì)象對(duì)應(yīng)的類繼承并實(shí)現(xiàn)了其中handleMessage函數(shù),通過(guò)這個(gè)實(shí)現(xiàn)的handleMessage函數(shù)處理消息)。
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }
二、Message機(jī)制的用途
Message機(jī)制有兩種用途:
定時(shí)執(zhí)行:延遲到指定時(shí)間執(zhí)行消息調(diào)度
線程通訊:將某些操作在其他線程中排隊(duì)執(zhí)行
1、定時(shí)執(zhí)行
通過(guò)本線程的Handler將消息延遲到指定時(shí)間執(zhí)行,相當(dāng)于定時(shí)器的作用
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- public final boolean postDelayed(Runnable r, long delayMillis)
還可以在指定時(shí)間到期之前,通過(guò)removeMessages取消執(zhí)行
2、線程通訊
Android的UI是單線程的,Android希望UI線程能夠給予User快速的反應(yīng),如果UI線程花費(fèi)太多的時(shí)間做幕后的事情,吵過(guò)5秒 鐘,Android就會(huì)給出錯(cuò)誤提示。因此為了避免拖住UI,一下較費(fèi)時(shí)的工作應(yīng)該交給獨(dú)立的線程去執(zhí)行。但是如果幕后的線程來(lái)執(zhí)行UI對(duì) 象,Android又會(huì)發(fā)出錯(cuò)誤信息,所以UI線程與幕后線程需要進(jìn)行通訊。UI線程將工作分發(fā)給幕后線程,幕后線程執(zhí)行后將相應(yīng)的狀態(tài)返回給UI線程, 讓UI線程對(duì)UI做成相應(yīng)的更新。
總結(jié):所謂的消息機(jī)制其實(shí)很簡(jiǎn)單,實(shí)現(xiàn)這種機(jī)制需要只需要四步:
1、實(shí)例化Looper(因?yàn)閷?shí)例化Handler時(shí)需要一個(gè)looper);
2、實(shí)例化Handler,這里需要覆蓋handleMessage方法,處理收到的消息;
3、 實(shí)例化Message對(duì)象,調(diào)用已經(jīng)實(shí)例化好的handler對(duì)象的obtainMessage方法,把數(shù)據(jù)傳給obtainMessage方 法,obtainMessage方法就會(huì)實(shí)例化一個(gè)Message對(duì)象。(這里也可以發(fā)送實(shí)現(xiàn)Runnable接口的對(duì)象);
4、調(diào)用Handler的sendMessage方法把實(shí)例化好的Message對(duì)象發(fā)送出去。對(duì)每個(gè)線程過(guò)程都是一樣的,只要按照上面的四個(gè)步驟來(lái)就可以發(fā)送和接收消息了。
通過(guò)全文的閱讀相信你已經(jīng)對(duì)Message機(jī)制應(yīng)用有了一定的理解,希望今后多多實(shí)踐練習(xí),一定會(huì)熟練掌握。