Master Android Native Looper 之 Native Looper簡(jiǎn)介

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的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市台妆,隨后出現(xiàn)的幾起案子蹬刷,更是在濱河造成了極大的恐慌,老刑警劉巖频丘,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件办成,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡搂漠,警方通過(guò)查閱死者的電腦和手機(jī)迂卢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)桐汤,“玉大人而克,你說(shuō)我怎么就攤上這事≌” “怎么了员萍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拣度。 經(jīng)常有香客問(wèn)我碎绎,道長(zhǎng),這世上最難降的妖魔是什么抗果? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任筋帖,我火速辦了婚禮,結(jié)果婚禮上冤馏,老公的妹妹穿的比我還像新娘日麸。我一直安慰自己,他們只是感情好逮光,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布代箭。 她就那樣靜靜地躺著,像睡著了一般涕刚。 火紅的嫁衣襯著肌膚如雪嗡综。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天副女,我揣著相機(jī)與錄音蛤高,去河邊找鬼蚣旱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛戴陡,可吹牛的內(nèi)容都是我干的塞绿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼恤批,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼异吻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喜庞,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诀浪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后延都,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雷猪,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年晰房,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了求摇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殊者,死狀恐怖与境,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猖吴,我是刑警寧澤摔刁,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站海蔽,受9級(jí)特大地震影響共屈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜准潭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一趁俊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刑然,春花似錦、人聲如沸暇务。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)垦细。三九已至择镇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間括改,已是汗流浹背腻豌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吝梅。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓虱疏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親苏携。 傳聞我的和親對(duì)象是個(gè)殘疾皇子做瞪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容