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对象。


链接:https://www.jianshu.com/p/368cbce8ec8a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值