Android應(yīng)用程序消息處理機(jī)制(Looper、Handler)分析(8)
執(zhí)行完這些IdleHandler之后,線程下次調(diào)用nativePollOnce函數(shù)時(shí),就不設(shè)置超時(shí)時(shí)間了。
因?yàn)?,很有可能在?zhí)行IdleHandler的時(shí)候,已經(jīng)有新的消息加入到消息隊(duì)列中去了。
正因?yàn)槿绱耍?/p>
要重置nextPollTimeoutMillis的值:
- [java] view plaincopy// While calling an idle handler, a new message could
- ve been delivered
- // so go back and look again for a pending message without waiting.
- nextPollTimeoutMillis = 0;
分析完MessageQueue的這個(gè)next函數(shù)之后,我們就要深入分析一下JNI方法nativePollOnce了,看看它是如何進(jìn)入等待狀態(tài)的, 這個(gè)函數(shù)定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:
- [cpp] view plaincopystatic void
- android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
- jint ptr, jint timeoutMillis) {
- NativeMessageQueue* nativeMessageQueue =
- reinterpret_cast(ptr);
- nativeMessageQueue->pollOnce(timeoutMillis);
- }
這個(gè)函數(shù)首先是通過(guò)傳進(jìn)入的參數(shù)ptr取回前面在Java層創(chuàng)建MessageQueue對(duì)象時(shí)在JNI層創(chuàng)建的NatvieMessageQueue對(duì)象,然后調(diào)用它的pollOnce函數(shù):
- [cpp] view plaincopyvoid NativeMessageQueue::pollOnce(int timeoutMillis)
- mLooper->pollOnce(timeoutMillis);
- }
這里將操作轉(zhuǎn)發(fā)給mLooper對(duì)象的pollOnce函數(shù)處理,這里的mLooper對(duì)象是在C++層的對(duì)象,它也是在前面在JNI層創(chuàng)建的 NatvieMessageQueue對(duì)象時(shí)創(chuàng)建的,它的pollOnce函數(shù)定義在frameworks/base/libs/utils /Looper.cpp文件中:
- [cpp] view plaincopyint Looper::pollOnce(int timeoutMillis, int* outFd,
- t* outEvents, void** outData) {
- int result = 0;
- for (;;) {
- ......
- if (result != 0) {
- ......
- return result;
- }
- result = pollInner(timeoutMillis);
- }
- }
為了方便討論,我們把這個(gè)函數(shù)的無(wú)關(guān)部分都去掉,它主要就是調(diào)用pollInner函數(shù)來(lái)進(jìn)一步操作,如果pollInner返回值不等于0,這個(gè)函數(shù)就可以返回了。
函數(shù)pollInner的定義如下:
- [cpp] view plaincopyint Looper::pollInner(int timeoutMillis) {
- ......
- int result = ALOOPER_POLL_WAKE;
- ......
- #ifdef LOOPER_USES_EPOLL
- struct epoll_event eventItems[EPOLL_MAX_EVENTS];
- int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS,
- meoutMillis);
- bool acquiredLock = false;
- #else
- ......
- #endif
- if (eventCount < 0) {
- if (errno == EINTR) {
- goto Done;
- }
- LOGW("Poll failed with an unexpected error, errno=%d", errno);
- result = ALOOPER_POLL_ERROR;
- goto Done;
- }
- if (eventCount == 0) {
- ......
- result = ALOOPER_POLL_TIMEOUT;
- goto Done;
- }
- ......
- #ifdef LOOPER_USES_EPOLL
- for (int i = 0; i < eventCount; i++) {
- int fd = eventItems[i].data.fd;
- uint32_t epollEvents = eventItems[i].events;
- if (fd == mWakeReadPipeFd) {
- if (epollEvents & EPOLLIN) {
- awoken();
- } else {
- LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.",
- ollEvents);
- }
- } else {
- ......
- }
- }
- if (acquiredLock) {
- mLock.unlock();
- }
- Done: ;
- #else
- ......
- #endif
- ......
- return result;
- }