活用
Android
線程間通信的
Message
機(jī)制
1.1.
Message
代碼在frameworks/base/core/java/android/Os/Message.java中。
Message.obtain 函數(shù):有多個(gè)obtain函數(shù),主要功能一樣,只是參數(shù)不一樣。作用是從Message Pool中取出一個(gè)Message,如果Message Pool中已經(jīng)沒有Message可取則新建一個(gè)Message返回,同時(shí)用對(duì)應(yīng)的參數(shù)給得到的Message對(duì)象賦值。
Message Pool : 大小為10個(gè);通過Message.mPool->(Message并且Message.next)-> (Message并且Message.next)-> (Message并且Message.next)...構(gòu)造一個(gè)Message Pool。Message Pool的第一個(gè)元素直接new出來,然后把Message.mPool(static類的static變量)指向它。其他的元素都是使用完的 Message通過Message的recycle函數(shù)清理后放到Message Pool(通過Message Pool最后一個(gè)Message的next指向需要回收的Message的方式實(shí)現(xiàn))。下圖為Message Pool的結(jié)構(gòu):
1.2. MessageQueue
MessageQueue
里面有一個(gè)收到的Message的對(duì)列:
MessageQueue.mMessages(static 變量)->( Message并且Message.next)-> ( Message并且Message.next)->...,下圖為接收消息的消息隊(duì)列:
上層代碼通過 Handler的sendMessage等函數(shù)放入一個(gè)message到MessageQueue里面時(shí)最終會(huì)調(diào)用MessageQueue的 enqueueMessage函數(shù)。enqueueMessage根據(jù)上面的接收的Message的隊(duì)列的構(gòu)造把接收到的Message放入隊(duì)列中。
MessageQueue
的removeMessages函數(shù)根據(jù)上面的接收的Message的隊(duì)列的構(gòu)造把接收到的Message從隊(duì)列中刪除,并且調(diào)用對(duì)應(yīng)Message對(duì)象的recycle函數(shù)把不用的Message放入Message Pool中。
1.3.
Looper
Looper
對(duì)象的創(chuàng)建是通過prepare函數(shù),而且每一個(gè)Looper對(duì)象會(huì)和一個(gè)線程關(guān)聯(lián)
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
Looper 對(duì) 象創(chuàng)建時(shí)會(huì)創(chuàng)建一個(gè)MessageQueue,主線程默認(rèn)會(huì)創(chuàng)建一個(gè)Looper從而有MessageQueue,其他線程默認(rèn)是沒有 MessageQueue的不能接收Message,如果需要接收Message則需要通過prepare函數(shù)創(chuàng)建一個(gè)MessageQueue。具體操 作請(qǐng)見示例代碼。
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
prepareMainLooper 函數(shù)只給主線程調(diào)用(系統(tǒng)處理,程序員不用處理),它會(huì)調(diào)用prepare建立Looper對(duì)象和MessageQueue。
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
Loop 函 數(shù)從MessageQueue中從前往后取出Message,然后通過Handler的dispatchMessage函數(shù)進(jìn)行消息的處理(可見消息的處 理是Handler負(fù)責(zé)的),消息處理完了以后通過Message對(duì)象的recycle函數(shù)放到Message Pool中,以便下次使用,通過Pool的處理提供了一定的內(nèi)存管理從而加速消息對(duì)象的獲取。至于需要定時(shí)處理的消息如何做到定時(shí)處理,請(qǐng)見 MessageQueue的next函數(shù),它在取Message來進(jìn)行處理時(shí)通過判斷MessageQueue里面的Message是否符合時(shí)間要求來決 定是否需要把Message取出來做處理,通過這種方式做到消息的定時(shí)處理。
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
//
break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to
" + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
1.4.
Handler
Handler 的構(gòu)造函數(shù)表示Handler會(huì)有成員變量指向Looper和MessageQueue,后面我們會(huì)看到?jīng)]什么需要這些引用;至于callback是實(shí)現(xiàn)了Callback接口的對(duì)象,后面會(huì)看到這個(gè)對(duì)象的作用。
public Handler(Looper looper, Callback callback) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
}
public interface Callback {
public boolean handleMessage(Message msg);
}
獲取消息:直接通過Message的obtain方法獲取一個(gè)Message對(duì)象。
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
return Message.obtain(this, what, arg1, arg2, obj);
}
發(fā)送消息:通過MessageQueue的enqueueMessage把Message對(duì)象放到MessageQueue的接收消息隊(duì)列中
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
線 程如何處理MessageQueue中接收的消息:在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ù),通過這個(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);
}
}
Runnable 說明:Runnable只是一個(gè)接口,實(shí)現(xiàn)了這個(gè)接口的類對(duì)應(yīng)的對(duì)象也只是個(gè)普通的對(duì)象,并不是一個(gè)Java中的Thread。Thread類經(jīng)常使用Runnable,很多人有誤解,所以這里澄清一下。
從上可知以下關(guān)系圖:
其中清理Message是Looper里面的loop函數(shù)指把處理過的Message放到Message的Pool里面去,如果里面已經(jīng)超過最大值10個(gè),則丟棄這個(gè)Message對(duì)象。
調(diào)用Handler是指Looper里面的loop函數(shù)從MessageQueue的接收消息隊(duì)列里面取出消息,然后根據(jù)消息指向的Handler對(duì)象調(diào)用其對(duì)應(yīng)的處理方法。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
