Android系統(tǒng)中最重要的輔助類(lèi)Looper,定義了一個(gè)線程間通信與同步的方法冰垄。其源代碼位于/system/core/libutils/Looper.cpp,頭文件位于/system/core/include/utils/Looper.h
Native Looper 涉及到的關(guān)鍵對(duì)象
Looper 回調(diào)函數(shù)
定義如下:
typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
Looper事件回調(diào)权她,當(dāng)fd的某個(gè)事件發(fā)生時(shí)虹茶,如果設(shè)置了回調(diào)冀瓦,則調(diào)用之前已經(jīng)注冊(cè)的方法,fd指明了哪個(gè)fd發(fā)生了事件写烤,events指明了poll事件的bit mask翼闽,通常是EVENT_INPUT,data給了參數(shù)洲炊。
該函數(shù)如果返回1感局,則looper會(huì)繼續(xù)接受回調(diào),如果返回0暂衡,則looper會(huì)取消該fd的事件以及回調(diào):
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
removeFd(fd, responce.request.seq);
}
Message
代表了一個(gè)事件询微,通過(guò)一個(gè)int值來(lái)指出是什么樣的Message。
MessageHandler/WeakMessageHandler
事件處理的基類(lèi)狂巢,子類(lèi)通過(guò)實(shí)現(xiàn)handleMessage來(lái)實(shí)現(xiàn)特定Message的處理撑毛。WeakMessageHandler包含了一個(gè)MessageHandler的弱指針
LooperCallback/SimpleLooperCallback
Looper回調(diào),實(shí)際上就是保存一個(gè)Looper_callbackFunc指針的包裝基類(lèi)唧领。
Looper事件
以下事件都是定義在Looper中的enum藻雌,由Looper_pollOnce和Looper_pollAll返回。
- 1 POLL_WAKE: poll被wake方法在超時(shí)前喚醒斩个,沒(méi)有任何callback執(zhí)行且沒(méi)有任何fd有事件到達(dá)胯杭。
- 2 POLL_CALLBACK: 至少一個(gè)callback被執(zhí)行了。
- 3 POLL_TIMEOUT: 超時(shí)
- 4 POLL_ERROR: 錯(cuò)誤發(fā)生
FD事件受啥,代表Looper可以被監(jiān)控的FD事件做个,以下事件可以位組合。
- 1 EVENT_INPUT: fd有數(shù)據(jù)可讀滚局。
- 2 EVENT_OUTPUT: fd有數(shù)據(jù)可寫(xiě)
- 3 EVENT_ERROR: fd出錯(cuò)居暖,Looper總是報(bào)告錯(cuò)誤,應(yīng)用沒(méi)必要設(shè)置該flag
- 4 EVENT_HANGUP: 遠(yuǎn)端pipe或socket關(guān)閉導(dǎo)致本端掛起藤肢,Looper總是報(bào)告該事件太闺,應(yīng)用不用設(shè)置
- 5 EVENT_INVALID: fd突然關(guān)閉,Looper總是報(bào)告該事件谤草,應(yīng)用不用設(shè)置
** CALLBACK設(shè)置選項(xiàng) **
PREPARE_ALLOW_NON_CALLBACKS 允許在調(diào)用Looper_addFd時(shí)不提供callback跟束,用戶必須檢查L(zhǎng)ooper_pollOnce或Looper_pollAll的返回值。
Looper的關(guān)鍵方法
構(gòu)造函數(shù)
Looper(bool allowNonCallbacks)
參數(shù)allowNonCallbacks表明是否可以在Looper_addFd時(shí)不提供callback丑孩。
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);**
inline int pollOnce(int timeoutMillis) {
return pollOnce(timeoutMillis, NULL, NULL, NULL);
}
poll一次的同時(shí)會(huì)執(zhí)行所有fd相關(guān)的callback冀宴,如果timeout為0,則立即返回温学,如果timeout為負(fù)數(shù)則會(huì)阻塞一直等待事件返回略贮。需要注意的是,該函數(shù)在所有callback全被執(zhí)行完前不會(huì)返回,所以如果callback內(nèi)有阻塞方法逃延,會(huì)導(dǎo)致pollOnce阻塞览妖。該函數(shù)的返回值意義如下:
POLL_WAKE 被wake方法喚醒,沒(méi)有一個(gè)事件ready且callback被執(zhí)行
POLL_CALLBACK 如果至少有一個(gè)callback被調(diào)用
POLL_TIMEOUT 超時(shí)
POLL_ERROR 錯(cuò)誤
0 返回的數(shù)值代表了某個(gè)指定fd有事件發(fā)生但是沒(méi)有注冊(cè)callback揽祥,僅當(dāng)此時(shí)outFd讽膏,outEvents和outData將保存相關(guān)的fd,events和數(shù)據(jù)拄丰。
int pollAll(int timeoutMills, int* outFd, int* outEvents, void* outData);
inline int pollAll(int timeoutMills) {
return pollAll(timeoutMills, NULL, NULL, NULL);
}
和pollOnce類(lèi)似府树,但是會(huì)直到所有callback被執(zhí)行完畢,并且數(shù)據(jù)被消耗或者某個(gè)fd有事件到達(dá)且沒(méi)有設(shè)置callback料按,該方法不會(huì)返回POLL_CALLBACK奄侠。
void wake();
執(zhí)行異步喚醒操作,該方法不會(huì)阻塞载矿。
int addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data);
int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
將一個(gè)fd加入Looper的監(jiān)控垄潮,如果已經(jīng)有同樣的fd,則舊的會(huì)被替換闷盔。參數(shù)fd是加入監(jiān)控的file descriptor弯洗,ident是pollOnce返回的標(biāo)識(shí)符,必須大于0或者POLL_CALLBACK(必須提供一個(gè)callback)馁筐。events是Looper感興趣的事件bit涂召。data是私有數(shù)據(jù)。
該方法有兩種用法:
有callback敏沉,當(dāng)事件發(fā)生時(shí),相關(guān)的callback會(huì)被調(diào)用炎码,該callback需要處理該fd上的所有事件盟迟,此時(shí)ident會(huì)被忽略。
無(wú)callback潦闲,當(dāng)事件發(fā)生時(shí)攒菠,ident將會(huì)在pollOnce中返回
int removeFd(int fd);
刪除一個(gè)已經(jīng)添加到Looper中的fd。當(dāng)該方法返回歉闰,用戶可以安全地關(guān)閉指定fd辖众,這里安全指的是Looper不在會(huì)使用該fd,但是有可能相關(guān)的callback還在執(zhí)行或會(huì)在未來(lái)某個(gè)事件點(diǎn)執(zhí)行(相關(guān)fd在被刪除前已經(jīng)有事件發(fā)生)和敬。這里建議要么在callback中調(diào)用該方法凹炸,要么在callback中返回0來(lái)自動(dòng)刪除≈绲埽或者可以用sp<LooperCallback>來(lái)保證最后一個(gè)引用才被釋放啤它。
void sendMessage(const sp<MessageHandler>& handler, const Message& message);
void sendMessageDelayed(...);
void sendMessageAtTime(...);
將一個(gè)message發(fā)送給指定的handler。
static sp<Looper>prepare(int opts);
將Looper初始化并和當(dāng)前調(diào)用線程綁定,如果當(dāng)前線程已經(jīng)有一個(gè)Looper变骡,則將返回已經(jīng)初始化的Looper离赫。
static void setForThread(const sp<Looper>& looper);
替換當(dāng)前調(diào)用線程的Looper對(duì)象。
static sp<Looper> getForThread();
返回調(diào)用線程的Looper對(duì)象塌碌。
這一篇先簡(jiǎn)單介紹Native Looper的關(guān)鍵成員變量及方法渊胸,下一篇將結(jié)合一些Android Native代碼的例子來(lái)看看具體是如何使用Native Looper的