Master Android Native Looper 之 Native Looper簡介

Android系統(tǒng)中最重要的輔助類Looper,定義了一個線程間通信與同步的方法。其源代碼位于/system/core/libutils/Looper.cpp,頭文件位于/system/core/include/utils/Looper.h


Native Looper 涉及到的關(guān)鍵對象

Looper 回調(diào)函數(shù)

定義如下:

typedef int (*Looper_callbackFunc)(int fd, int events, void* data);

Looper事件回調(diào),當(dāng)fd的某個事件發(fā)生時,如果設(shè)置了回調(diào),則調(diào)用之前已經(jīng)注冊的方法,fd指明了哪個fd發(fā)生了事件,events指明了poll事件的bit mask,通常是EVENT_INPUT,data給了參數(shù)。
該函數(shù)如果返回1,則looper會繼續(xù)接受回調(diào),如果返回0,則looper會取消該fd的事件以及回調(diào):

int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
    removeFd(fd, responce.request.seq);
}

Message

代表了一個事件,通過一個int值來指出是什么樣的Message。

MessageHandler/WeakMessageHandler

事件處理的基類,子類通過實現(xiàn)handleMessage來實現(xiàn)特定Message的處理。WeakMessageHandler包含了一個MessageHandler的弱指針

LooperCallback/SimpleLooperCallback

Looper回調(diào),實際上就是保存一個Looper_callbackFunc指針的包裝基類。

Looper事件

以下事件都是定義在Looper中的enum,由Looper_pollOnce和Looper_pollAll返回。

  • 1 POLL_WAKE: poll被wake方法在超時前喚醒,沒有任何callback執(zhí)行且沒有任何fd有事件到達(dá)。
  • 2 POLL_CALLBACK: 至少一個callback被執(zhí)行了。
  • 3 POLL_TIMEOUT: 超時
  • 4 POLL_ERROR: 錯誤發(fā)生

FD事件,代表Looper可以被監(jiān)控的FD事件,以下事件可以位組合。

  • 1 EVENT_INPUT: fd有數(shù)據(jù)可讀。
  • 2 EVENT_OUTPUT: fd有數(shù)據(jù)可寫
  • 3 EVENT_ERROR: fd出錯,Looper總是報告錯誤,應(yīng)用沒必要設(shè)置該flag
  • 4 EVENT_HANGUP: 遠(yuǎn)端pipe或socket關(guān)閉導(dǎo)致本端掛起,Looper總是報告該事件,應(yīng)用不用設(shè)置
  • 5 EVENT_INVALID: fd突然關(guān)閉,Looper總是報告該事件,應(yīng)用不用設(shè)置

** CALLBACK設(shè)置選項 **

PREPARE_ALLOW_NON_CALLBACKS 允許在調(diào)用Looper_addFd時不提供callback,用戶必須檢查Looper_pollOnce或Looper_pollAll的返回值。

Looper的關(guān)鍵方法

構(gòu)造函數(shù)

Looper(bool allowNonCallbacks)

參數(shù)allowNonCallbacks表明是否可以在Looper_addFd時不提供callback。

int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);**
inline int pollOnce(int timeoutMillis) {   
  return pollOnce(timeoutMillis, NULL, NULL, NULL);
}

poll一次的同時會執(zhí)行所有fd相關(guān)的callback,如果timeout為0,則立即返回,如果timeout為負(fù)數(shù)則會阻塞一直等待事件返回。需要注意的是,該函數(shù)在所有callback全被執(zhí)行完前不會返回,所以如果callback內(nèi)有阻塞方法,會導(dǎo)致pollOnce阻塞。該函數(shù)的返回值意義如下:

POLL_WAKE 被wake方法喚醒,沒有一個事件ready且callback被執(zhí)行
POLL_CALLBACK 如果至少有一個callback被調(diào)用
POLL_TIMEOUT 超時
POLL_ERROR 錯誤

0 返回的數(shù)值代表了某個指定fd有事件發(fā)生但是沒有注冊callback,僅當(dāng)此時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類似,但是會直到所有callback被執(zhí)行完畢,并且數(shù)據(jù)被消耗或者某個fd有事件到達(dá)且沒有設(shè)置callback,該方法不會返回POLL_CALLBACK。

void wake();

執(zhí)行異步喚醒操作,該方法不會阻塞。

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);

將一個fd加入Looper的監(jiān)控,如果已經(jīng)有同樣的fd,則舊的會被替換。參數(shù)fd是加入監(jiān)控的file descriptor,ident是pollOnce返回的標(biāo)識符,必須大于0或者POLL_CALLBACK(必須提供一個callback)。events是Looper感興趣的事件bit。data是私有數(shù)據(jù)。

該方法有兩種用法:
有callback,當(dāng)事件發(fā)生時,相關(guān)的callback會被調(diào)用,該callback需要處理該fd上的所有事件,此時ident會被忽略。
無callback,當(dāng)事件發(fā)生時,ident將會在pollOnce中返回

int removeFd(int fd);

刪除一個已經(jīng)添加到Looper中的fd。當(dāng)該方法返回,用戶可以安全地關(guān)閉指定fd,這里安全指的是Looper不在會使用該fd,但是有可能相關(guān)的callback還在執(zhí)行或會在未來某個事件點執(zhí)行(相關(guān)fd在被刪除前已經(jīng)有事件發(fā)生)。這里建議要么在callback中調(diào)用該方法,要么在callback中返回0來自動刪除?;蛘呖梢杂胹p<LooperCallback>來保證最后一個引用才被釋放。

void sendMessage(const sp<MessageHandler>& handler, const Message& message);
void sendMessageDelayed(...);
void sendMessageAtTime(...);

將一個message發(fā)送給指定的handler。

static sp<Looper>prepare(int opts);

將Looper初始化并和當(dāng)前調(diào)用線程綁定,如果當(dāng)前線程已經(jīng)有一個Looper,則將返回已經(jīng)初始化的Looper。

static void setForThread(const sp<Looper>& looper);

替換當(dāng)前調(diào)用線程的Looper對象。

static sp<Looper> getForThread();

返回調(diào)用線程的Looper對象。


這一篇先簡單介紹Native Looper的關(guān)鍵成員變量及方法,下一篇將結(jié)合一些Android Native代碼的例子來看看具體是如何使用Native Looper的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容