Master Android Native Looper 之 Native Looper简介

Android系统中最重要的辅助类Looper,定义了一个线程间通信与同步的方法。其源代码位于/system/core/libutils/Looper.cpp,头文件位于/system/core/include/utils/Looper.h


Native Looper 涉及到的关键对象

Looper 回调函数

定义如下:

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

Looper事件回调,当fd的某个事件发生时,如果设置了回调,则调用之前已经注册的方法,fd指明了哪个fd发生了事件,events指明了poll事件的bit mask,通常是EVENT_INPUT,data给了参数。
该函数如果返回1,则looper会继续接受回调,如果返回0,则looper会取消该fd的事件以及回调:

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

Message

代表了一个事件,通过一个int值来指出是什么样的Message。

MessageHandler/WeakMessageHandler

事件处理的基类,子类通过实现handleMessage来实现特定Message的处理。WeakMessageHandler包含了一个MessageHandler的弱指针

LooperCallback/SimpleLooperCallback

Looper回调,实际上就是保存一个Looper_callbackFunc指针的包装基类。

Looper事件

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

  • 1 POLL_WAKE: poll被wake方法在超时前唤醒,没有任何callback执行且没有任何fd有事件到达。
  • 2 POLL_CALLBACK: 至少一个callback被执行了。
  • 3 POLL_TIMEOUT: 超时
  • 4 POLL_ERROR: 错误发生

FD事件,代表Looper可以被监控的FD事件,以下事件可以位组合。

  • 1 EVENT_INPUT: fd有数据可读。
  • 2 EVENT_OUTPUT: fd有数据可写
  • 3 EVENT_ERROR: fd出错,Looper总是报告错误,应用没必要设置该flag
  • 4 EVENT_HANGUP: 远端pipe或socket关闭导致本端挂起,Looper总是报告该事件,应用不用设置
  • 5 EVENT_INVALID: fd突然关闭,Looper总是报告该事件,应用不用设置

** CALLBACK设置选项 **

PREPARE_ALLOW_NON_CALLBACKS 允许在调用Looper_addFd时不提供callback,用户必须检查Looper_pollOnce或Looper_pollAll的返回值。

Looper的关键方法

构造函数

Looper(bool allowNonCallbacks)

参数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一次的同时会执行所有fd相关的callback,如果timeout为0,则立即返回,如果timeout为负数则会阻塞一直等待事件返回。需要注意的是,该函数在所有callback全被执行完前不会返回,所以如果callback内有阻塞方法,会导致pollOnce阻塞。该函数的返回值意义如下:

POLL_WAKE 被wake方法唤醒,没有一个事件ready且callback被执行
POLL_CALLBACK 如果至少有一个callback被调用
POLL_TIMEOUT 超时
POLL_ERROR 错误

0 返回的数值代表了某个指定fd有事件发生但是没有注册callback,仅当此时outFd,outEvents和outData将保存相关的fd,events和数据。

int pollAll(int timeoutMills, int* outFd, int* outEvents, void* outData);
inline int pollAll(int timeoutMills) {
     return pollAll(timeoutMills, NULL, NULL, NULL);
}

和pollOnce类似,但是会直到所有callback被执行完毕,并且数据被消耗或者某个fd有事件到达且没有设置callback,该方法不会返回POLL_CALLBACK。

void wake();

执行异步唤醒操作,该方法不会阻塞。

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的监控,如果已经有同样的fd,则旧的会被替换。参数fd是加入监控的file descriptor,ident是pollOnce返回的标识符,必须大于0或者POLL_CALLBACK(必须提供一个callback)。events是Looper感兴趣的事件bit。data是私有数据。

该方法有两种用法:
有callback,当事件发生时,相关的callback会被调用,该callback需要处理该fd上的所有事件,此时ident会被忽略。
无callback,当事件发生时,ident将会在pollOnce中返回

int removeFd(int fd);

删除一个已经添加到Looper中的fd。当该方法返回,用户可以安全地关闭指定fd,这里安全指的是Looper不在会使用该fd,但是有可能相关的callback还在执行或会在未来某个事件点执行(相关fd在被删除前已经有事件发生)。这里建议要么在callback中调用该方法,要么在callback中返回0来自动删除。或者可以用sp<LooperCallback>来保证最后一个引用才被释放。

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

将一个message发送给指定的handler。

static sp<Looper>prepare(int opts);

将Looper初始化并和当前调用线程绑定,如果当前线程已经有一个Looper,则将返回已经初始化的Looper。

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

替换当前调用线程的Looper对象。

static sp<Looper> getForThread();

返回调用线程的Looper对象。


这一篇先简单介绍Native Looper的关键成员变量及方法,下一篇将结合一些Android Native代码的例子来看看具体是如何使用Native Looper的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容